原型链(__proto__)和原型(prototype)深入挖掘

    JS中到处是对象,对象之间往往会通过__proto__链接在了一起,这种链接的现象被称为原型链(极少数的对象会没有原型,比如Object.create(null)产生的对象里面没有任何属性,非常‘空’,我们称它为字典,这种字典对象适合存放数据,不必担心原型带来的副作用)。对象的产生有两种方式,一种是字面量,另外一种是通过函数。一般的对象他们的原型链的顶点是Object.prototype。通过构造函数形式产生的对象,他们的__proto__会自动关联构造函数的prototype。

   而构造函数的prototype是什么,它的原型链最终又指向了哪里呢?这个问题的答案是:函数的prototype是一个在函数声明阶段就会产生的对象(prototype只有函数才会有),这个对象只有两个属性constructor和__proto__,其中__proto__指向了我们原型链的顶点Object.prototype。constructor指向函数自身,里面包括了函数一些基本描述信息比如函数名称,参数个数等等。

   有意思的是constructor里面既有__proto__又有prototype,他们之间有什么关系和差别呢?首先prototype描述的是原型对象,它是一个实实在在的对象,__proto__是用来描述对象间的关联关系的,最终会指向一个prototype原型对象。函数由Function衍生而来,所以函数的__proto__指向的是Function.prototype。Function是由Object衍生而来,有意思的事情又发生了,Function的__proto__却并不指向Object.prototype,而是指向Function.prototype这个标准的内置对象。Function.prototype.__proto__才是指向我们的原型链顶点Object.prototype。

  稍微小结一下:

1一般的对象,它的原型链指向的是顶端的Object.prototype,譬如{‘name’: ‘code’},函数内置的constructor,Function.prototype等等。

2通过构造函数产生的对象,它的原型链首先指向构造函数的原型

3函数的原型链首先会指向Function.prototype,譬如function f () {}, Array(), Object()等等。

    无论是对象还是函数,原型链最终都会指向我们的顶端Object.prototype。接着我们来看constructor中的prototype是什么,结果它指向了我们函数的原型。比如f是我们定义的函数,那么f.prototype.constructor.prototype === f.prototype,还记得我之前说过的“constructor指向函数自身”吗,它的表达式形式如下f.prototype.consturctor ===  f 。有了这个前提,f.prototype.constructor.prototype === f.prototype显然成立,而事实也的确如此。这简直像极了数学中的证明两个数相等的命题。现在我们已经从原型链的一端走到了顶点,虽然它的起点有三个,普通对象,构造函数产生的对象,函数,但最终都汇聚到了Object.prototype。作为顶端对象,Object.prototype有一些基础的公共方法比如toString,valueOf,hasOwnProperty等等。术之尽头,炁体源流。原型链终,Object.prototype。

猜你喜欢

转载自blog.csdn.net/qq_34295211/article/details/84960816