js原型的知识很重要,但想搞清楚原型,proto prototype constructor三个属性(指针)之间的区别和联系必须要搞清楚。
如果我们不知道这三个指针平时在哪里出没,那还怎么理关系?那真是剪不断,理还乱。
默认情况下:constructor只会出现在原型对象中。prototype只会出现在构造函数中。*__ proto __ 会出现在构造函数和对象实例和原型对象中.*
如果认为constructor是我们创建对象实例的时候默认的属性就大错特错了。
function Person(){
}
Person.prototype.name="dddd";
Person.prototype.sex="男";
Person.prototype.love="badminton";
Person.prototype.age=20;
Person.prototype.sayContent=function(){
alert("Hello world");
};
var p=new Person();
为什么我们经常可以用 alert(p.constructor===Person);//true
不要认为constructor是创建的对象实例p默认自带的属性,之所以p.constructor===Person是true,是这条语句在执行p.constructor时,先在创建的对象实例p中找constructor属性,很可惜,没找到,就沿着原型链,通过对象实例默认属性 _ proto _,找到原型对象,碰巧在原型对象中找到constructor属性,而该属性又指向构造函数Person,所以才为true.
好,再看一个不是默认情况的。
重写原型对象
function Person(){
}
Person.prototype={
name:"chendong",
sex:"男",
love:"rocket",
age:20,
sayContent:function(){
alert("hello world");
}
};
var p=new Person();
console.log(p.constructor===Person);//false
console.log(p.constructor===Object);//true
在执行p.constructor时,编译器先在p的对象实例中找constructor属性,由上面可以知道,没找到。然后通过对象实例p中默认属性_ proto _ ,沿着原型链找到原型对象,但默认的原型对象Person.prototype被重写了,现在原型对象里也没有constructor属性。那怎么办呢?当然是沿着原型链继续网上找呀。这时候我们在原型对象中发现还有一个默认自带属性 _ proto _ ,虽然我们重写时没定义,但重写的原型对象中一定存在。这里的 _ proto _指向 Object原型对象 而Object原型对象中恰好有constructor属性,该指针指向 构造函数 function Object(){},所以console.log(p.constructor===Object);//true 至此真相大白。
所以我们可以看到重写的对象原型如果没有显性定义constructor指针的指向,他在原型对象中是不存在的。
当我们显性定义constructor:Person;加入重写的原型对象中如下:
function Person(){
}
Person.prototype={
constructor:Person,
name:"chendong",
sex:"男",
love:"rocket",
age:20,
sayContent:function(){
alert("hello world");
}
};
var p=new Person();
console.log(p.constructor===Person);//true
console.log(p.constructor===Object);//true
console.log(p.constructor===Person);//true
通过这个栗子我们可以很清楚的看见 原型链的主链是通过 _ proto _属性来实现连接的。而prototype constructor只不过是这个”主链”两边的“支链”
我们学习原型链只需关注 :
如果没有继承关系:对象实例 ———> 原型对象 ——->Object.prototype原型对象
如果有继承关系:对象实例 ———> 原型对象 ——->其他的构造函数的原型对象
这条线上的 这些对象的 _ proto _ 而不需要关注 构造函数的 _ proto _ 的属性。
原型链主链是由 原型对象中的 _ proto _ 的属性构建的。和构造函数中的 _ proto _ 属性无关。构造函数中prototype属性和 默认状态下的原型函数的constructor 属性只是 原型链的分支。不参与主链原型链的生成。所以我们学习原型链知识时 关注 构造函数 _ proto _ 属性就走偏了。但是属性查找,主链支链都参加,这点也很重要。
举一个原型链的栗子:
function animal(){}
animal.prototype.action=function(){
alert("I can't get out of the air");
};
function People(){}
People.prototype=new animal();
var p=new People();
原型链 为 :
主链为:
p._ proto _——> People.prototype;
People.prototype._ proto _——–>animal.prototype;
animal.prototype._ proto _———>Object.prototype;
主链两边的分支为:
People.prototype——>People.prototype原型对象;
animal.prototype——->animal.prototype原型对象;
animal.prototype.constructor——>animal构造函数。
p.constructor===animal构造函数;这是按原型链推导出来的。
注意:People.protype原型对象中没有constructor属性。