【js基础】js中_proto_ prototype constructor之间的关系

来源:互联网 发布:福岛核事故知乎 编辑:程序博客网 时间:2024/05/22 05:26

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属性。

阅读全文
0 0