ES6 分析__proto__和prototype区别和关系,并追溯原型链和继承链

本文为自己理解js原型链和继承链关系所写。

 

1.在JS里,万物皆对象。对象皆有实例属性__proto__,(在chrome中标记为[[Prototype]])称为隐式原型,对应一个指针,指向一个特殊的对象(原型对象,即继承的对象,暂时可简单理解为父对象),__proto__保证了实例对象能够访问在构造函数原型中定义的属性和方法。(实例属性即对象作为实例对象时候拥有的属性)

2.方法(Function)
Function这个特殊的对象,除了实例属性__proto__之外,还有单独拥有函数属性prototype,对应一个指针,指向的方法的原型对象(即Function.prototype指向这个对象),这个Function.prototype原型对象的用途就是包含所有实例对象共享的属性和方法(即js中的继承概念)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。(函数属性即对象作为函数或方法对象时候拥有的属性)

上自己画的笔记图

图中使用Person()代替var Person=function(name){this.name = name;}定义的对象

 

 

 

上代码

/*与下面定义Person作用基本相同
var Person=function(name){  
        this.name = name;
}  
*/

/*与下面定义Person作用基本相同
var str = "this.name = " + "name;";
var Person = new Function("name", str);
*/

function Person(name){  
        this.name = name;
}

//创建实例
p=new Person("lily");

//控制台输出
console.dir("---------------1---------------");
console.dir(p);
console.dir(Person.prototype);
console.dir(p.__proto__);
console.dir(p.__proto__ === Person.prototype);//输出true
console.dir(Person.__proto__);


//输出Function相关
console.dir(" ");
console.dir("---------------2---------------");
console.dir(Function.prototype);
console.dir(Function.prototype.__proto__);
console.dir(Function.__proto__);

//输出Object相关
console.dir(" ");
console.dir("---------------3---------------");
console.dir(Object.prototype);
console.dir(Object.prototype.__proto__);
console.dir(Object.__proto__);

console.dir(" ");
console.dir("---------------4---------------");
console.dir(typeof Person);
console.dir(typeof Person.prototype);
console.dir(typeof Object);
console.dir(typeof Object.prototype);
console.dir(typeof Function);
console.dir(typeof Function.prototype);

 

  打开360安全浏览器(版本号: 13.1.5390.0|内核版本: 86.0.4240.198)开发者工具(F12)查看console的输出结果如下,(chrome不显示__proto__属性)

总览

 

详情

  

如上,p.__proto__和Person.prototype都指向原型对象(记为A),A作为原型对象拥有constructor属性,指向其构造函数Persion(name)。

A作为实例对象拥有__proto__属性,指向了--构造函数Object()对应的原型对象Object.prototype(记为B),展开B上图(自行调试代码,分割线123分别输出了Person,Function,Object方法相关的属性,输出对比可发现B与Object.prototype相同)

自行调试上述代码,查看输出发现可以发现Person.__proto__和Function.prototype指向的对象相同,即Person()函数对象(函数对象) 是构造Function()函数的实例,印证了一切js自定义函数皆源于Function函数。调试代码查看输出结果可一一验证上述结构图中的原型链关系(绿线create代表new,绿线constructor指回构造函数,黑线__proto__属性指向,橘线prototype指向)

实际上,上面的原型链关系图为显性的结果,在调试理解Function和Object时纠结不清,容易混淆。先不用太过纠结是Object()构造函数创造了Function()实例函数对象,还是Function()构造函数创造了Object()实例函数对象,这只是控制台输出的表象关系。因为Function,Object,Array等所有的js内置函数对象,都由browser实现,而不是由Function()实现。Function只创建自定义函数。

 

下面几条以继承链的角度来看上述的关系图,会更清晰。

 

1.逻辑上先有对象,后有函数对象,先有__proto__,后有prototype

2.js继承机制是基于原型的继承(暂时理解为构造函数的实例对象与构造函数的原型对象的关系)

3.使用typeof发现,Function.prototype是个函数对象

4.将__proto__属性看做继承关系指针(下图标记为绿色箭头虚线),实例对象继承自原型对象,可以提炼为继承链关系如下

5.上图中1分支为Function类型函数对象,234分支为Object类型对象(3分支new Function()特例为Function类型)

6.4分支字面量对象不经构造函数create,3分支new Object()对象特殊,都直接继承继承Object.prototype。

 

上述两个图,大致上能表达原型链和继承链。

posted @ 2021-05-27 13:12  RoarInWind  阅读(261)  评论(0编辑  收藏  举报