本文为了处理以下题目:
__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
属性,而这个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
要领。
为什么会继续原型对象的要领?
由于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{}
参考文章: