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{} 

《constructor, prototype, __proto__ 详解》

参考文章:

  1. 壮大的原型和原型链

  2. js原型链看图申明

  3. 明白javascript原型

  4. javascript类和继续:constructor

  5. javascript探秘:组织函数

    原文作者:苹果小萝卜
    原文地址: https://segmentfault.com/a/1190000003017751
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞