`

[转载]constructor, prototype, __proto__ 详解

阅读更多

本文为了解决以下问题:

  • __proto__(实际原型)和prototype(原型属性)不一样!!!

  • constructor属性(原型对象中包含这个属性,实例当中也同样会继承这个属性)

  • prototype属性(constructor.prototype原型对象)

  • __proto__属性(实例指向原型对象的指针)

首先弄清楚几个概念:

什么是对象

若干属性的集合

什么是原型?

原型是一个对象,其他对象可以通过它实现继承。

哪些对象有原型?

所有的对象在默认情况下都有一个原型,因为原型本身也是对象,所以每个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端)

任何一个对象都可以成为原型

接下来就是最核心的内容:

constructor 属性

constructor属性始终指向创建当前对象的构造函数。

    var arr=[1,2,3];
    console.log(arr.constructor); //输出 function Array(){}
    var a={};
    console.log(arr.constructor);//输出 function Object(){}
    var bool=false;
    console.log(bool.constructor);//输出 function Boolean(){}
    var name="hello";
    console.log(name.constructor);//输出 function String(){}
    var sayName=function(){}
    console.log(sayName.constrctor)// 输出 function Function(){}
    
    //接下来通过构造函数创建instance
    function A(){}
    var a=new A();
    console.log(a.constructor); //输出 function A(){}

以上部分即解释了任何一个对象都有constructor属性,指向创建这个对象的构造函数

prototype属性

注意:prototype是每个函数对象都具有的属性,被称为原型对象,而__proto__属性才是每个对象才有的属性。一旦原型对象被赋予属性和方法,那么由相应的构造函数创建的实例会继承prototype上的属性和方法

    //constructor : A
    //instance : a
    function A(){}
    var a=new A();

    A.prototype.name="xl";
    A.prototype.sayName=function(){
        console.log(this.name);
    }
    
    console.log(a.name);// "xl"
    a.sayName();// "xl"
    
    //那么由constructor创建的instance会继承prototype上的属性和方法

constructor属性和prototype属性

每个函数都有prototype属性,而这个prototypeconstructor属性会指向这个函数。

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }
    
    var person=new Person("xl");
    
    console.log(person.constructor); //输出 function Person(){}
    console.log(Person.prototype.constructor);//输出 function Person(){}
    console.log(Person.constructor); //输出 function Function(){}

如果我们重写(重新定义)这个Person.prototype属性,那么constructor属性的指向就会发生改变了。

    Person.prototype={
        sayName:function(){
            console.log(this.name);
        }
    }
    
    console.log(person.constructor==Person); //输出 false (这里为什么会输出false后面会讲)
    console.log(Person.constructor==Person); //输出 false
    
    console.log(Person.prototype.constructor);// 输出 function Object(){}  
    //这里为什么会输出function Object(){}
    //还记得之前说过constructor属性始终指向创建这个对象的构造函数吗?
    
    Person.prototype={
        sayName:function(){
            console.log(this.name);
        }
    }
    //这里实际上是对原型对象的重写:
    Person.prototype=new Object(){
        sayName:function(){
            console.log(this.name);
        }
    }
    //看到了吧。现在Person.prototype.constructor属性实际上是指向Object的。
    
    //那么我如何能将constructor属性再次指向Person呢?
    Person.prototype.constructor=Person;

接下来解释为什么,看下面的例子

    function Person(name){
        this.name = name;
    }
    
    var personOne=new Person("xl");
    
    Person.prototype = {
        sayName: function(){
            console.log(this.name);
        }
    };
    
    var personTwo = new Person('XL');
    
    console.log(personOne.constructor == Person); //输出true
    console.log(personTwo.constructor == Person); //输出false   
    //大家可能会对这个地方产生疑惑?为何会第二个会输出false,personTwo不也是由Person创建的吗?这个地方应该要输出true啊?
    //这里就涉及到了JS里面的原型继承
    //这个地方是因为person实例继承了Person.prototype原型对象的所有的方法和属性,包括constructor属性。当Person.prototype的constructor发生变化的时候,相应的person实例上的constructor属性也会发生变化。所以第二个会输出false;
    //当然第一个是输出true,因为改变构造函数的prototype属性是在personOne被创建出来之后。

接下解释__proto__prototype属性
同样拿上面的代码来解释:

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }
    var person=new Person("xl");
    person.sayName(); //输出 "xl"

    //constructor : Person
    //instance : person
    //prototype : Person.prototype

首先给构造函数的原型对象Person.prototype赋给sayName方法,由构造函数Person创建的实例person会继承原型对象上的sayName方法。

为什么会继承原型对象的方法?

因为ECMAscript的发明者为了简化这门语言,同时又保持继承性,采用了链式继承的方法。

constructor创建的每个instance都有个__proto__属性,它指向constructor.prototype。那么constrcutor.prototype上定义的属性和方法都会被instance所继承.

    function Person(name){
        this.name=name;
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    }
    
    var personOne=new Person("a");
    var personTwo=new Person("b");
    
    personOne.sayName(); // 输出  "a"
    personTwo.sayName(); //输出 "b"
    
    console.log(personOne.__proto__==Person.prototype); // true
    console.log(personTwo.__proto__==Person.prototype); // true
    
    console.log(personOne.constructor==Person); //true
    console.log(personTwo.constructor==Person); //true
    console.log(Person.prototype.constructor==Person); //true
    
    console.log(Person.constructor); //function Function(){}
    console.log(Person.__proto__.__proto__); // Object{} 



 

 

转载地址:https://segmentfault.com/a/1190000003017751

 

  • 大小: 112.7 KB
  • 大小: 53.8 KB
0
0
分享到:
评论

相关推荐

    详解帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)

    JavaScript中的`prototype`、`__proto__`和`constructor`是理解JavaScript面向对象编程的关键概念。这篇文章通过图解的方式深入浅出地解析了这三个概念之间的关系。 首先,`__proto__`属性是对象独有的,它指向对象...

    javascript 中__proto__和prototype详解

    理解__proto__和prototype这两个概念对于深入掌握JavaScript面向对象编程至关重要。 首先我们来看__proto__属性。每个JavaScript对象都拥有一个__proto__属性,这个属性指向该对象的原型对象。原型对象是另一个对象...

    图文详解JavaScript的原型对象及原型链

    首先,我们来区分两个关键的属性:`prototype`和`__proto__`。 1. `prototype`:主要用于构造函数,它是构造函数的一个属性,用于定义实例对象将继承的属性和方法。当我们创建一个函数(即构造函数)时,该函数的`...

    详解JavaScript中基于原型prototype的继承特性_.docx

    同时,为了保持`constructor`属性的正确指向,我们需要显式地将`SubType.prototype.constructor`设置为`SubType`。 在JavaScript中,`instanceof`操作符可以用来检查一个对象是否属于某个构造函数的实例,而`...

    prototype 源码 注释

    **JavaScript中的Prototype详解** 在JavaScript中,Prototype是一个非常重要的概念,它是面向对象编程的基础。本文将深入探讨Prototype的原理、用途及其在JavaScript中的实现方式,同时结合提供的`prototype.js`...

    Biu-blog:个人博客

    constructor, prototype, __proto__ 详解 Webpack webpack-dev-server使用方法,看完还不会的来找我~ 基于后编译的国际化解决方案 Webpack hash 生成规则 Webpack Ruleset loader过滤器 Webpack Loader 高手进阶(一)...

    JavaScript 继承详解(二)

    当试图访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript会查找其`__proto__`,也就是其构造函数的`prototype`,如果`prototype`也没有,就会继续查找`prototype`的`__proto__`,这个过程一直持续到...

    我所理解的从原型到原型链.pdf

    这里,`person.__proto__`实际上就是`Person.prototype`,这意味着`person`对象的原型就是`Person`函数的`prototype`对象。 #### 原型链 原型链是由一系列`__proto__`属性组成的链式结构。当我们试图访问一个对象...

    js原型链详解

    ### JavaScript原型与原型链详解 JavaScript作为一门基于原型的语言,其原型和原型链的概念是理解和掌握JS继承机制的关键。接下来将详细阐述这些概念。 #### 普通对象与函数对象 在JavaScript中,一切皆为对象,...

    JavaScript prototype属性详解

    新对象会通过其内部属性(通常在浏览器中表示为__proto__)指向构造函数的prototype属性,从而获得prototype上定义的属性和方法。这就是所谓的原型链。 理解prototype的工作原理之前,需要先了解JavaScript中的作用...

    JavaScript面试题

    - 访问`Object.prototype.constructor`会得到`Object`函数。 - 通过`Object.prototype.__proto__`获取`Object`原型的原型,结果为`null`,表明`Object {}`原型对象是原型链的终点。 #### 四、初识`Function` - ...

    详解Javascript中prototype属性(推荐)

    如果没有,它会向上查找其`__proto__`(非标准)或`[[Prototype]]`(标准)链接的原型对象,直到找到属性或者遍历完整个原型链。这就是所谓的原型链。 5. **constructor属性** `constructor`是每个`prototype`对象...

    javascript Object与Function使用.docx

    每个函数都有一个名为`prototype`的属性,而通过函数和`new`操作符创建的对象则具有一个`__proto__`属性,该属性指向创建该对象的构造函数的`prototype`属性。 **原型链结构**: ``` __proto__ foo ----------- Foo...

    JavaScript中构造函数与原型链之间的关系详解

    - `demo.constructor.prototype`实际上也是`Demo.prototype`,因为`constructor`属性的值是构造函数,而构造函数的`prototype`属性指向实例继承的原型。 引用图例中的关系可以这样理解: - `Demo.prototype`是一个...

    ES6 javascript中Class类继承用法实例详解

    `B.prototype.__proto__`也会指向`A.prototype`,表示`B`的方法继承自`A`的方法。 ### 使用技巧 1. **覆盖父类的方法**:子类可以覆盖父类的方法来实现特定的功能。 2. **调用父类的方法**:使用`super`关键字调用...

    详解js中的原型,原型对象,原型链.docx

    ### 详解JS中的原型、原型对象与原型链 #### 前言 JavaScript是一种基于原型的语言,这使得它与其他面向对象编程语言有所不同。在JavaScript中,每个对象都有一个原型对象,而原型对象又可能有自己的原型对象,从而...

    JavaScript继承的特性与实践应用深入详解

    当一个函数被创建时,它的`prototype`属性会被初始化为一个对象,其中包含一个`constructor`属性,该属性指向构造函数本身。 在实现继承时,常常会使用到`new`关键字。`new`操作符会创建一个新的对象,并将该对象的...

    Prototype 学习 Prototype对象

    ### Prototype对象详解 #### 一、概述 在JavaScript领域中,Prototype框架是一个强大的库,它简化了许多复杂的DOM操作,使得开发者能够更轻松地处理事件、动态创建元素等。本篇文章将深入探讨Prototype对象的核心...

Global site tag (gtag.js) - Google Analytics