最近在看设计模式时,遇到一些关于继承原型之类的知识,对于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
复制代码