JS中原型和原型鏈深入理解

JavaScript代碼中定義函數,或者調用Function創建函數時,最終都會以類似這樣的形式調用Function函數:var newFun = new Function(funArgs, funBody)

舉個例子,child1,child2都是Mother的孩子,且是雙胞胎。(雖然不是很好,但是還是很能說明問題的)

function Mother(name){  this.name = name;  this.father = 'baba';}var child1 = new Mother('huahua');var child2 = new Mother('huihui');

如果有一天,發現孩子的父親其實是Baba,那麼就要對孩子每一個孩子的father屬性。

child1.father ='Baba';console.log(child2.father) // baba

也就是說修改了其中一個孩子的father屬性不會影響到下一個,屬性的值無法共享。

正是這個原因才提出來prototype屬性,把需要共享的屬性放到構造函數也就是父類的實例中去。

__proto__

__proto__屬性是每一個對象以及函數都隱含的一個屬性。對於每一個含有__proto__屬性,他所指向的是創建他的構造函數的prototype。原型鏈就是通過這個屬性構件的。

想像一下,如果一個函數對象(也成為構造函數)a的prototype是另一個函數對象b構件出的實例,a的實例就可以通過__proto__與b的原型鏈起來。而b的原型其實就是Object的實例,所以a的實例對象,就可以通過原型鏈和object的prototype鏈接起來。

function a(){}function b(){}var b1 = new b();a.prototype = b1;var a1 = new a();console.log(a1.__proto__===b1);//trueconsole.log(a1.__proto__.__proto__===b.prototype) //trueconsole.log(a1.__proto__.__proto__.__proto__===Object.prototype) //true

如果要理清原型和原型鏈的關係,首先要明確一下幾個概念:

1.JS中的所有東西都是對象,函數也是對象, 而且是一種特殊的對象

2.JS中所有的東西都由Object衍生而來, 即所有東西原型鏈的終點指向Object.prototype

3.JS對象都有一個隱藏的__proto__屬性,他指向創建它的構造函數的原型,但是有一個例外,Object.prototype.__proto__指向的是null。

4.JS中構造函數和實例(對象)之間的微妙關係

構造函數通過定義prototype來約定其實例的規格, 再通過 new 來構造出實例,他們的作用就是生產對象.

function Foo(){}var foo = new Foo();foo其實是通過Foo.prototype來生成實例的。

構造函數本身又是方法(Function)的實例, 因此也可以查到它的__proto__(原型鏈)

function Foo(){}等價於var Foo= new Function();

而Function實際上是

function Function(){ Native Code}也就是等價於var Function= new Function();

所以說Function是通過自己創建出來的。正常情況下對象的__proto__是指向創建它的構造函數的prototype的.所以Function的__proto__指向的Function.prototype

Object 實際上也是通過Function創建出來的

typeof(Object)//function所以,function Object(){ Native Code}等價於var Object = new Function();

那麼Object的__proto__指向的是Function.prototype,也即是

Object.__proto__ === Function.prototype //true

下面再來看Function.prototype的__proto__指向哪裡

因為JS中所有的東西都是對象,那麼,Function.prototype 也是對象,既然是對象,那麼Function.prototype肯定是通過Object創建出來的,所以,

Function.prototype.__proto__ === Object.prototype //true

綜上所述,Function和Object的原型以及原型鏈的關係可以歸納為下圖。

JS中原型和原型鏈深入理解

對於單個的對象實例,如果通過Object創建,

var obj = new Object();

那麼它的原型和原型鏈的關係如下圖

JS中原型和原型鏈深入理解

如果通過函數對象來創建,

function Foo(){}var foo = new Foo();

那麼它的原型和原型鏈的關係如下圖

JS中原型和原型鏈深入理解

那JavaScript的整體的原型和原型鏈中的關係就很清晰了,如下圖所示

JS中原型和原型鏈深入理解


分享到:


相關文章: