constructor、prototype、__proto__详解笔记

最近在看设计模式时,遇到一些关于继承原型之类的知识,对于constructor、prototype、proto__彼此的区别关联有些懵逼,搜了一些文章,现将对此知识的理解整理如下(笔记来源于以下地址:hanekaoru.com/constructor…-%E5%92%8C-prototype-%E5%8C%BA%E5%88%AB%E5%92%8C%E5%85%B3%E7%B3%BB/ ,segmentfault.com/a/119000000…

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

var arr = [1,2,3]
console.log(arr.constructor)==> ƒ Array() { [native code] }

var a = {}
console.log(a.constructor)==> ƒ Object() { [native code] }

var bool = false;
console.log(bool.constructor)==> ƒ Boolean() { [native code] }

var name = "hello"
console.log(name.constructor)==>ƒ String() { [native code] }

var sayName = function(){}
console.log(sayName.constructor)==>ƒ Function() { [native code] }

function A(){}
var a = new A();
console.log(a.constructor)==>ƒ A(){}
console.log(A.prototype.constructor)==>f A(){}
复制代码

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

function A(){}
var a = new A();
console.log(a.prototype.constructor)
==>VM1101:1 Uncaught TypeError: Cannot read property 'constructor' of undefined
复制代码

其实在输入a.prototype时会自动提示__proto__,而且a.的属性列表中没有prototype的属性

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

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方法

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

var obj = { a : 1 };
console.log(obj.__proto__ === Object.prototype);    // true
 
 
var str = new String('123');
console.log(str.__proto__ === String.prototype);    // true
 
 
function Point(){};
var Circle = Object.create(Point);
 
console.log(Circle.__proto__ === Point);            // true
console.log(Circle.__proto__ === Point.prototype);  // false
 
 
var p = new Point();
console.log(Point.__proto__);   // function Empty() {}
console.log(Point.prototype);   // Point {}
 
console.log(p.__proto__);       // Point {}
console.log(p.prototype);       // undefined

// obj 一般对象
var obj = {}
 
console.log(obj.constructor)  // function Object() { }
console.log(obj.prototype)  // undefined
console.log(obj.__proto__)  // Object { }  [ 注意:这个是对象,不是构造函数 Object () { } ]
 
 
console.log(obj.__proto__.constructor)  // function Object() { }
console.log(obj.__proto__.__proto__)  // null
console.log(obj.__proto__.prototype)  // undefined
 
 
 
// -------------------------------------------------------------------------
 
 
 
// 函数(包括普通函数,构造函数,原生函数[Array,Object,String等])
function fn () {}
 
console.log(fn.constructor)  // Function() { }
console.log(fn.prototype)  // Object {constructor: function} 构造函数
console.log(fn.__proto__)  // function () { }  空函数 empty
 
console.log(fn.__proto__.constructor)  // Function() { }
console.log(fn.__proto__.__proto__)  // Object { }   [ 注意:这个是对象,不是构造函数 Object () { } ]
console.log(fn.__proto__.prototype)  // undefined
复制代码

你可能感兴趣的:(constructor、prototype、__proto__详解笔记)