关于原型链的知识,我刚开始就是看一篇一篇的博客,知识有点零碎,后面看了下《JS高级程序设计》,又大致整合了一下。下面记录的是,对于一条完整的原型链长什么样这个问题的思考。
借用一段在《JS高级程序设计》中的一段代码:
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
此段代码中,构造函数Person
,原型对象Person.prototype
以及实例对象person1
和person2
的关系如下图所示:
按照书上的解释,很好理解,但很显然,它并不是一条完整的原型链,并且我也有疑问:书中给出的示例图中没有画构造函数Person和原型对象Person.prototype的_proto_属性。
首先:_proto_
属性是个对象都有,那么,在万物皆对象的JS中,构造函数Person
和原型对象Person.prototype
的_proto_
属性又指向哪里呢??其次,就这个问题,结合上面给出的代码,可以将一条完整的原型链用类似上面的图画出来吗??
之前看了一篇博文,其中分析了_proto_
应该指向谁的问题,举了下面这个例子,可能直接看会有点蒙圈,原文: JS原型链简单图解 - 最骚的就是你 - 博客园
对应的示例代码如下:
var A = function(){};
var a = new A();
console.log(a.__proto__); //A {}(A.prototype即A的原型对象)
console.log(a.__proto__.__proto__); //Object {}(Object.prototype即Object的原型对象)
console.log(a.__proto__.__proto__.__proto__); //null
其实,对于a._proto_ ==A.prototype
以及Object.prototype._proto_==null
比较好理解:
使用函数表达式方法创建的函数变量A,就是新的函数变量a的构造函数,所以a的原型对象就是其构造函数的prototype所指的对象:A.prototype
而Object.prototype._proto_为什么是null可以参考:为什么原型链的终点是null,而不是Object.prototype?- 余百炼的博客 - CSDN博客
然而,为什么A.prototype
的原型是Object.prototype
,即A.prototype._proto_==Object.prototype
怎么解释呢??
其实,原型链是指对象的原型链,这个链上的节点都是一级一级的原型对象,所以原型链上的所有节点都是对象!!!因此这就好理解了,A.prototype
是一个对象,然后它是Object
的一个实例,所以它的原型是Object.prototype
。
这里需要注意的是,a虽然是原型链上的起点,它也是对象,但是它的原型并不是直接就是Object.prototype,它的原型是其构造函数的prototype所指的对象:A.prototype
其实这个图描述的还只是局部 ,不利于理解,请看下面的图:(图片取自javascript - 为什么原型链的终点是null,而不是Object.prototype - SegmentFault 思否 )
从这张大图中我们可以看出来,
fun._proto_
)都是Function.prototype
,无论是JS原生的构造函数如Function还是Object等还是用户自定义的构造函数如上图的Foo;fun.prototype._proto_
)都是Object.prototype
,无论是自定义的还是原生的(Object除外);根据这个图,可以更好的理解下面这两句话:
_proto_
是任何对象都有的属性,而JS里万物都是对象,所以会形成一条_proto_
连起来的链条,递归访问_proto_
必须最终到头,并且值是null;prototype
这样的话,关系就比较明了了。所以,文章开头的那段代码的原型链应该如下图所示:
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
趁着这个机会,可以讨论一下原生构造函数Object
和Function
到底什么关系?
从上图中我们可以把Function
和Object
部分单独摘出来:
Function._proto_==Function.prototype==function(){}
Function._proto_._proto_==Object.prototype
Function._proto_._proto_._proto_==Object.prototype._proto_==null
Object._proto_ === Function.prototype==function(){}
Object._proto_._proto_==Object.prototype
Object._proto_._proto_._proto_==null
从上图中可以看到构造函数之间的关系如下:
Object.prototype.constructor===Object
Object instanceof Function;//true
Object.constructor===Function
Function.prototype.constructor===Function
Function instanceof Object;//true
Function.constructor===Function
原文:https://www.cnblogs.com/ch206265/p/10629689.html