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

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

原型

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

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

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

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

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

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

    function Bar() {}

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

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

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

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

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

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

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

屬性查找

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

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

原型屬性

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

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

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

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

性能

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

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

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

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

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

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

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

總結(jié)

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