1.prototype和__proto__有什么不可告人的关系?
说道原型对象,那一定绕不开几个概念:
prototype,__proto__,constructor。
首先解释一下prototype是什么,原型对象。V8引擎给所有函数内置的一个对象。也就是只要创建的了一个函数(类也算,因为类的本质也是函数)。那么这个函数就会携带一个原型对象prototype。
再来说一下__proto__,不管是函数还是对象,都具有__proto__这个属性。现在,我来带给你一个非常牛逼的万能公式,来说明__proto__和prototype之间的关系
不管函数还是对象的__proto__,一定等价于对应实例化的类的原型对象。
什么意思,我现在举个例子:
function People(name){
this.name = name
}
let p1 = new People();
let arr = new Array();
let obj = new Object();
现在我有三个对戏,p1(通过People类实例化出来的),arr(通过Array类实例化出来的),obj(通过Object类实例化出来的)。
那么我可以说:
p1.__proto__ === People.prototype;
arr.__proto__ === Array.prototype;
obj.__proto__ === Object.prototype;
那有人就会说了,你这不全面。不只是对象才有__proto__属性啊;函数的__proto__怎么算呢?
OK,对于上面的People类来说,如果我换一种写法!!!!!如下:
let People = new Function('name','this.name = name')
是不是一下就通透了,就完美。完全可以说People是通过Function类实例化出来的,所以!!!
People.__proto__ === Function.prototype;
Array.__proto__ === Function.prototype;
Object.__proto__ === Function.prototype;
除了实例化对象和函数,是否还有其他的什么东西具有__proto__属性呢?
还有一个特例,就是prototype。我们知道原型对象是创建函数的时候,V8给带出来的,但我们管它是谁带出来的呢?原型对象原型对象,原型对象还是对象,是对象就是Object实例化出来的,所以:
People.prototype.__proto__ === Object.prototype
如果推到这里,你就会发现,如果Object.prototype也指向Object的原型对象。那么原型链就没头了,所以:
Object.prototype.__proto__ === null
现在,对于原型链和原型对象,是不是非常通透。赶紧去控制台试试,记住上面最重要的公式:
不管函数还是对象的__proto__,一定等价于对应实例化的类的原型对象!!!
2.constructor又在这里面搞什么飞机
对于constructor,和prototype,__proto__之间的关系。并不能像上面那样找到一个比较明确的公式。
所以,这里我们针对于不同情况下,列出不同事物的constructor和事物的prototype或者__proto__之间的对应关系。反正也不多,就简单记一下好了。
(1)对象的constructor:
对象的constructor等价于,对应实例化类的本身:
[].constructor === Array
(2)函数的constructor:
函数的constructor等价于,Function:
Array.constructor === Function
(3)prototype的constructor
prototype的constructor等价于,对应函数的本身:
Array.prototype.constructor === Array
(4)__proto__的constructor
__proto__的constructor等价于,对应实例化类的本身:
[].__proto__.constructor === Array
对于上面的公式,可别来一个数学上的等价关系奥。比如由第一条和第四条,你来一个交换律:
[] === [].__proto__
这可不兴交换奥,只能说明二者共用了一个constructor,并不能说明二者是一个东西奥。