JavaScript:我對原型鏈的理解


原型鏈一直是個很抽象的概念,看不到,摸不着.隨着最近對JavaScript進一步的學習,我對原型鏈有了一點理解,下面講出來.

基礎知識

在JavaScript中,一共有兩種類型的值,原始值和對象值.每個對象都有一個內部屬性[[prototype]],我們通常稱之為原型.原型的值可以是一個對象,也可以是null.如果它的值是一個對象,則這個對象也一定有自己的原型.這樣就形成了一條線性的鏈,我們稱之為原型鏈.

訪問一個對象的原型可以使用ES5中的Object.getPrototypeOf方法,或者ES6中的__proto__屬性.

原型鏈的作用是用來實現繼承,比如我們新建一個數組,數組的方法就是從數組的原型上繼承而來的.

var arr = [];
arr.map
=== Array.prototype.map //arr.map是從arr.__proto__上繼承下來的,arr.__proto__也就是Array.prototype

圖形化原型鏈

雖然我們都說"原型鏈",但實際上,在不考慮網頁中frame的情況,js引擎在執行期間的某一時刻,所有存在的對象組成的是一棵原型樹.默認情況下,只有一棵樹.根節點可以說是Object.prototype,也可以說是null.

但我們可以再建立一棵原型樹,通過使用Object.create方法

var foo = Object.create(null);        //foo是一個對象,但它是游離的,不屬於已有的那棵原型樹
var bar = Object.create(foo);         //bar的原型是foo
var baz = Object.create(foo);         //baz的原型是foo 

這樣我們有了第二棵原型樹

遍歷原型鏈

我們沒有辦法遍歷到所有以某個對象為原型的對象,但我們可以向上遍歷,獲取到一個對象所有的上層原型,這個原型鏈必定是線性的,盡頭是null.

function getPrototypeChain(object) {
    var protoChain = [];
    while (object = object.__proto__) {
        protoChain.push(object);
    }
    protoChain.push(null);
    return protoChain;
}

試驗一下,不同的環境實現不同,顯示形式也不同.下面是在chrome控制台中的顯示.

>getPrototypeChain(new String(""))
[String, Object, null]                     //依次是String.prototype,Object.prototype,null
>getPrototypeChain(function(){}) [function Empty() {}, Object, null] //依次是Function.prototype,Object.prototype,null

內置類型的對象的原型鏈並不長,下面試試宿主對象.

>getPrototypeChain(document.createElement("div"))
[HTMLDivElement, HTMLElement, Element, Node, Object, null]

這個就長多了.

超長原型鏈

可以看出來,我們平時使用的對象並沒有很長的原型鏈.但可以自己構造一個.

function Foo() {}

for (var i = 0; i < 100; i++) {
    Foo.prototype["prop" + i] = i;
    Foo.prototype = new Foo;
}
console.dir(getPrototypeChain(new Foo));

最后的這個new Foo有多少個上層原型呢?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM