成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JS面向?qū)ο蟮某绦蛟O(shè)計(jì)_創(chuàng)建對(duì)象之組合使用模式-2

xuexiangjys / 3088人閱讀

摘要:組合使用構(gòu)造函數(shù)模式和原型模式創(chuàng)建自定義類型的最常見(jiàn)方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。也就是說(shuō),寄生構(gòu)造函數(shù)模式下,構(gòu)造函數(shù)創(chuàng)建的對(duì)象與在構(gòu)造函數(shù)外創(chuàng)建的對(duì)象沒(méi)有什么不同。

前言

最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaScript高級(jí)程序設(shè)計(jì)第三版》。

1. 組合使用構(gòu)造函數(shù)模式和原型模式

創(chuàng)建自定義類型的最常見(jiàn)方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。

構(gòu)造函數(shù),用于定義實(shí)例對(duì)象的屬性。

原型模式,用于定義方法和共享的屬性。

這樣的話, 每個(gè)實(shí)例對(duì)象都有屬于自己屬性的一份副本, 但同時(shí)又共享著對(duì)方法的引用,最大程度地節(jié)省了內(nèi)存。

這種混合模式還支持向構(gòu)造函數(shù)傳遞參數(shù), 可謂集兩種模式之長(zhǎng)。

//構(gòu)造函數(shù)模式與原型模式, 應(yīng)用示例

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Sharon", "Sandy"];
}

Person.prototype = {
    constructor: Person,
    sayName: function(){
        console.log(this.name);
    }
}

var person1 = new Person("Shaw", 28, "Designer");
var person2 = new Person("Roc", 27, "Doctor");

console.log(person1.sayName()); // "Shaw"
console.log(person2.sayName()); // "Roc"

person1.friends.push("Vans");

console.log(person1.friends); // ["Sharon", "Sandy", "Vans"]
console.log(person2.friends); // ["Sharon", "Sandy"]

console.log(person1.friends === person2.friends); // false
console.log(person1.sayName === person2.sayName); // true

在這個(gè)例子中,實(shí)例對(duì)象的屬性都是在構(gòu)造函數(shù)中定義的, 所有實(shí)例對(duì)象共享的屬性constructor和sayName()方法則是在原型中定義的。 修改person1.friends并不會(huì)影響到person2.friends, 因?yàn)閜erson1和person2實(shí)例對(duì)象分別引用不同的數(shù)組。

==這種構(gòu)造函數(shù)與原型模式混合使用的模式,是目前在ECMAScript中使用最廣泛、認(rèn)同度最高的一種創(chuàng)建自定義類型的方法。 可以說(shuō), 這是定義引用類型的一種默認(rèn)模式。==

2. 動(dòng)態(tài)原型模式

有其他OO語(yǔ)言經(jīng)驗(yàn)的開(kāi)發(fā)人員在看到獨(dú)立的構(gòu)造函數(shù)和原型時(shí),很可能會(huì)感覺(jué)到困惑。

動(dòng)態(tài)原型模式正是致力于解決這個(gè)問(wèn)題的一個(gè)方案,它把所有信息都封裝在了構(gòu)造函數(shù)中。

通過(guò)在構(gòu)造函數(shù)中初始化原型(在一些必要的情況下),又保持了同時(shí)使用構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)。

==換句話說(shuō),可以通過(guò)檢查某個(gè)存在的方法是否有效, 來(lái)決定是否需要初始化原型。==

//動(dòng)態(tài)原型模式示例代碼

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    if(typeof this.sayName != "function") {
        Person.prototype.sayName = function() {
            console.log(this.name);
        }
    }
}
4
var person1 = new Person("Shaw", 18, "Designer");
person1.sayName(); // "Shaw"

注意構(gòu)造函數(shù)代碼中的這一部分。

if(typeof this.sayName != "function") {
    Person.prototype.sayName = function() {
        console.log(this.name);
    }
}

沒(méi)有像原型模式一樣,顯式的定義原型的屬性和方法。而是調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)完全原型的初始化。

如:

function Person(){
}

Person.prototype.sayName = function() {
    console.log(this.name);
}

這段代碼只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)執(zhí)行。此后,原型完成初始化,不需要在做什么修改了。
不夠要記住,這里對(duì)原型所做的修改,能夠立即在所有實(shí)例對(duì)象中得到反映。
因此,這種做法可以說(shuō)非常完美。
其中if語(yǔ)句檢查的可以是初始化之后,應(yīng)該存在的任何屬性或方法- 不必用一大堆if語(yǔ)句檢查每個(gè)屬性和方法;
只需要檢查其中一個(gè)即可。

對(duì)于采用這種模式創(chuàng)建的對(duì)象,還可以使用instanceof操作符確定它的類型。

注意: 使用動(dòng)態(tài)原型模式,不能使用對(duì)象字面量重寫原型。
如果在已經(jīng)創(chuàng)建了實(shí)例對(duì)象的情況重寫原型,那么會(huì)切斷已經(jīng)創(chuàng)建的實(shí)例對(duì)象與新原型之間的聯(lián)系。

3. 寄生構(gòu)造函數(shù)模式(不建議使用)

通常,在前述的幾種模式都不適用的情況下,可以使用(parasitic)構(gòu)造函數(shù)模式。

這種模式的基本思想是創(chuàng)建一個(gè)函數(shù),該函數(shù)的作用僅僅是封裝創(chuàng)建對(duì)象的代碼,然后返回新創(chuàng)建的對(duì)象。

從表面上看,這個(gè)函數(shù)又很像是典型的構(gòu)造函數(shù)。

function Person(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
}

var friend = new Person("Shaw", 18, "Engineer");

friend.sayName(); // "Shaw"

在這個(gè)例子中,Person函數(shù)創(chuàng)建了一個(gè)新對(duì)象,并以相應(yīng)的屬性和方法初始化該對(duì)象,然后返回了這個(gè)對(duì)象。

除了使用new操作符,并把使用的包裝函數(shù)叫做構(gòu)造函數(shù)之外,這個(gè)模式跟工廠模式是一模一樣的。

構(gòu)造函數(shù)在不返回值的情況下,使用new操作符,默認(rèn)返回一個(gè)實(shí)例對(duì)象。

而通過(guò)在構(gòu)造函數(shù)的末尾添加一個(gè)return語(yǔ)句, new操作符 + 構(gòu)造函數(shù) 可以重寫返回的值。

這個(gè)模式可以在特殊的情況下用來(lái)為對(duì)象創(chuàng)建構(gòu)造函數(shù)。

假設(shè)我們想創(chuàng)建一個(gè)具有額外方法的特殊數(shù)組。

由于不能直接修改Array構(gòu)造函數(shù), 因此可以使用這個(gè)模式。

function SpecialArray() {

    var values = new Array();

    values.push.apply(values, arguments);

    values.toPipedString = function() {
        return this.join("|");
    }

    return values;

}

var colors = new SpecialArray("red", "blue", "green");

console.log(colors.toPipedString()); //red|blue|green

在這個(gè)例子中,我們創(chuàng)建了一個(gè)名叫SpecialArray的構(gòu)造函數(shù)。

在這個(gè)構(gòu)造函數(shù)內(nèi)部,首先創(chuàng)建了一個(gè)數(shù)組,然后push()方法(用構(gòu)造函數(shù)接收到的所有參數(shù))初始化了數(shù)組的值。

雖然又給數(shù)組添加了一個(gè)toPipedString()方法, 該方法返回以豎線分隔的數(shù)組值。

最后返回整個(gè)數(shù)組。( [arguments, toPipedString: ?]

接著,我們調(diào)用了SpecialArray構(gòu)造函數(shù),向其中傳入了用于初始化數(shù)組的參數(shù)。(["red", "blue", "green", toPipedString: ?])。

最后,調(diào)用了toPipedString()方法。

==關(guān)于寄生構(gòu)造函數(shù)模式,需要注意:==

返回的對(duì)象與構(gòu)造函數(shù)或構(gòu)造函數(shù)的原型沒(méi)有關(guān)系。 也就是說(shuō),寄生構(gòu)造函數(shù)模式下,構(gòu)造函數(shù)創(chuàng)建的對(duì)象與在構(gòu)造函數(shù)外創(chuàng)建的對(duì)象沒(méi)有什么不同。

所以不能依賴instanceof操作符來(lái)確定對(duì)象的類型。

由于存在上述問(wèn)題,我們建議在可以使用其他模式的情況下,不要使用這種模式。

4. 穩(wěn)妥構(gòu)造函數(shù)模式

道格拉斯 克羅克福德(Douglas Crockford)famine了JavaScript中的穩(wěn)妥對(duì)象(durable objects)這一概念。

所謂穩(wěn)妥對(duì)象, 指的是沒(méi)有公共屬性,而且其方法也不引用this的對(duì)象。

穩(wěn)妥對(duì)象最適合在一些安全的環(huán)境中(這些環(huán)境中會(huì)禁止使用this和new),或者在防止數(shù)據(jù)被其他應(yīng)用程序(如Mashup 程序)改動(dòng)時(shí)使用。

穩(wěn)妥構(gòu)造函數(shù),遵循與寄生構(gòu)造函數(shù)類似的模式,但有兩點(diǎn)不同:

新創(chuàng)建對(duì)象的實(shí)例方法不引用this;

不使用new操作符調(diào)用構(gòu)造函數(shù)。

按照穩(wěn)妥構(gòu)造函數(shù)的要求,可以將前面的Person構(gòu)造函數(shù)重寫如下

function Person(name, age, job) {
    //創(chuàng)建要返回的對(duì)象
    var o = new Object();

    //可以在這里定義私有變量和函數(shù)

    //添加方法
    o.sayName = function() {
        console.log(name);
    }

    //返回對(duì)象
    return o;
}

var friend = Person("Shaw", 18, "Designer");

friend.sayName(); // "Shaw"

注意,以這種模式創(chuàng)建的對(duì)象中,除了使用sayName()方法之外,沒(méi)有其他方法訪問(wèn)name的值。

這樣,變量friend中保存的是一個(gè)穩(wěn)妥對(duì)象。

即使有其他代碼會(huì)給這個(gè)對(duì)象添加方法或數(shù)據(jù)成員,但也不可能有別的辦法訪問(wèn)傳入到構(gòu)造函數(shù)中的原始數(shù)據(jù)。

穩(wěn)妥構(gòu)造函數(shù)模式提供的這種安全性,使得他非常適合在某些安全執(zhí)行環(huán)境-例如,ADsafe(www.adsafe.org)和Caja (http://code.google.com/p/goog...) 提供的環(huán)境下使用。

與寄生構(gòu)造函數(shù)模式類似,使用穩(wěn)妥構(gòu)造函數(shù)模式創(chuàng)建的對(duì)象與構(gòu)造函數(shù)之間也沒(méi)有什么關(guān)系,因此instanceof操作符對(duì)這種對(duì)象也沒(méi)有意義。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98349.html

相關(guān)文章

  • JS面向對(duì)象程序設(shè)計(jì)繼承實(shí)現(xiàn)-寄生組合式繼承

    摘要:組合繼承最大的問(wèn)題就是無(wú)論在什么情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù)一次是在創(chuàng)建子類型原型的時(shí)候。好在,我們已經(jīng)找到了解決這個(gè)問(wèn)題方法寄生組合式繼承所謂寄生組合式繼承,即通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性,通過(guò)原型鏈的混成形式來(lái)繼承方法。 寄生組合式繼承 組合繼承是JavaScript最常用的繼承模式。 不過(guò),它也有自己的不足。 組合繼承最大的問(wèn)題就是無(wú)論在什么情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù)...

    y1chuan 評(píng)論0 收藏0
  • JS面向對(duì)象編程封裝

    摘要:在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造函數(shù)和原型構(gòu)造出來(lái)的。來(lái)看下面的例子優(yōu)點(diǎn)與單純使用構(gòu)造函數(shù)不一樣,原型對(duì)象中的方法不會(huì)在實(shí)例中重新創(chuàng)建一次,節(jié)約內(nèi)存。 我們所熟知的面向?qū)ο笳Z(yǔ)言如 C++、Java 都有類的的概念,類是實(shí)例的類型模板,比如Student表示學(xué)生這種類型,而不表示任何具體的某個(gè)學(xué)生,而實(shí)例就是根據(jù)這個(gè)類型創(chuàng)建的一個(gè)具體的對(duì)象,比如zhangsan、lisi,由...

    YFan 評(píng)論0 收藏0
  • 淺談JavaScript面向對(duì)象

    摘要:不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息。其次,按照一切事物皆對(duì)象的這餓極本的面向?qū)ο蟮姆▌t來(lái)說(shuō),類本身并不是一個(gè)對(duì)象,然而原型方式的構(gòu)造函數(shù)和原型本身也是個(gè)對(duì)象。第二個(gè)問(wèn)題就是在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。 前言 對(duì)象(Object)應(yīng)該算是js中最為重要的部分,也是js中非常難懂晦澀的一部分。更是面試以及框架設(shè)計(jì)中各出沒(méi)。寫這篇文章,主要參考與JavaScrip...

    cyixlq 評(píng)論0 收藏0
  • JS面向對(duì)象程序設(shè)計(jì)繼承實(shí)現(xiàn)-組合繼承

    摘要:實(shí)現(xiàn)思路使用原型鏈實(shí)現(xiàn)對(duì)原型方法和方法的繼承,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。繼承屬性繼承方法以上代碼,構(gòu)造函數(shù)定義了兩個(gè)屬性和。 JS面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的實(shí)現(xiàn)-組合繼承 前言:最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《Java...

    antz 評(píng)論0 收藏0
  • JS面向對(duì)象程序設(shè)計(jì)繼承實(shí)現(xiàn) - 原型鏈注意點(diǎn)

    摘要:第一種方式是使用操作符,只要檢測(cè)的實(shí)例對(duì)象中的原型鏈包含出現(xiàn)過(guò)的構(gòu)造函數(shù),結(jié)果就會(huì)返回。而這也正是組合使用原型模式和構(gòu)造函數(shù)模式的原因。在構(gòu)造函數(shù)模式中定義屬性,在原型模式中定義共享的方法。 前言:最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《Ja...

    pf_miles 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<