在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 原型
arguments 對象
類型轉(zhuǎn)換
構(gòu)造函數(shù)
instanceof 操作符
自動分號插入
為什么不要使用 eval
對象使用和屬性
作用域與命名空間
this 的工作原理
typeof 操作符
相等與比較
閉包和引用
數(shù)組遍歷與屬性
Array 構(gòu)造函數(shù)
原型
hasOwnProperty 函數(shù)
undefined 和 null
函數(shù)聲明與表達式
setTimeout 和 setInterval
for in 循環(huán)

原型

JavaScript 不包含傳統(tǒng)的類繼承模型,而是使用 prototype 原型模型。

雖然這經(jīng)常被當(dāng)作是 JavaScript 的缺點被提及,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。 實現(xiàn)傳統(tǒng)的類繼承模型是很簡單,但是實現(xiàn) JavaScript 中的原型繼承則要困難的多。

由于 JavaScript 是唯一一個被廣泛使用的基于原型繼承的語言,所以理解兩種繼承模式的差異是需要一定時間的。

第一個不同之處在于 JavaScript 使用原型鏈的繼承方式。

注意: 簡單的使用 Bar.prototype = Foo.prototype 將會導(dǎo)致兩個對象共享相同的原型。 因此,改變?nèi)我庖粋€對象的原型都會影響到另一個對象的原型,在大多數(shù)情況下這不是希望的結(jié)果。

    function Foo() {
        this.value = 42;
    }
    Foo.prototype = {
        method: function() {}
    };

    function Bar() {}

    // 設(shè)置Bar的prototype屬性為Foo的實例對象
    Bar.prototype = new Foo();
    Bar.prototype.foo = 'Hello World';

    // 修正Bar.prototype.constructor為Bar本身
    Bar.prototype.constructor = Bar;

    var test = new Bar() // 創(chuàng)建Bar的一個新實例

    // 原型鏈
    test [Bar的實例]
        Bar.prototype [Foo的實例] 
            { foo: 'Hello World' }
            Foo.prototype
                {method: ...};
                Object.prototype
                    {toString: ... /* etc. */};

上面的例子中,test 對象從 Bar.prototypeFoo.prototype 繼承下來;因此, 它能訪問 Foo 的原型方法 method。同時,它也能夠訪問那個定義在原型上的 Foo 實例屬性 value。

需要注意的是 new Bar() 不會創(chuàng)造出一個新的 Foo 實例,而是 重復(fù)使用它原型上的那個實例;因此,所有的 Bar 實例都會共享相同value 屬性。

注意: 不要使用 Bar.prototype = Foo,因為這不會執(zhí)行 Foo 的原型,而是指向函數(shù) Foo。 因此原型鏈將會回溯到 Function.prototype 而不是 Foo.prototype,因此 method 將不會在 Bar 的原型鏈上。

屬性查找

當(dāng)查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性為止。

到查找到達原型鏈的頂部 - 也就是 Object.prototype - 但是仍然沒有找到指定的屬性,就會返回 undefined

原型屬性

當(dāng)原型屬性用來創(chuàng)建原型鏈時,可以把任何類型的值賦給它(prototype)。

然而將原子類型賦給 prototype 的操作將會被忽略。

    function Foo() {}
    Foo.prototype = 1; // 無效

而將對象賦值給 prototype,正如上面的例子所示,將會動態(tài)的創(chuàng)建原型鏈。

性能

如果一個屬性在原型鏈的上端,則對于查找時間將帶來不利影響。特別的,試圖獲取一個不存在的屬性將會遍歷整個原型鏈。

并且,當(dāng)使用for in循環(huán)遍歷對象的屬性時,原型鏈上的所有屬性都將被訪問。

擴展內(nèi)置類型的原型

一個錯誤特性被經(jīng)常使用,那就是擴展 Object.prototype 或者其他內(nèi)置類型的原型對象。

這種技術(shù)被稱之為 monkey patching 并且會破壞封裝。雖然它被廣泛的應(yīng)用到一些 JavaScript 類庫中比如 Prototype, 但是我仍然不認為為內(nèi)置類型添加一些非標(biāo)準(zhǔn)的函數(shù)是個好主意。

擴展內(nèi)置類型的唯一理由是為了和新的 JavaScript 保持一致,比如 Array.forEach。

譯者注這是編程領(lǐng)域常用的一種方式,稱之為 Backport,也就是將新的補丁添加到老版本中。

總結(jié)

在寫復(fù)雜的 JavaScript 應(yīng)用之前,充分理解原型鏈繼承的工作方式是每個 JavaScript 程序員必修的功課。 要提防原型鏈過長帶來的性能問題,并知道如何通過縮短原型鏈來提高性能。 更進一步,絕對不要擴展內(nèi)置類型的原型,除非是為了和新的 JavaScript 引擎兼容。