使用設(shè)計(jì)模式創(chuàng)建JavaScript對象

JavaScript中沒有類的概念奥此,這給OO的編程帶來了一些困難款熬,但并不是不能解決的惕虑,使用以下幾種的設(shè)計(jì)模式可以解決JavaScript對象的創(chuàng)建問題庇忌。

工廠模式

工廠模式是創(chuàng)建對象的一種抽象方式义屏。

但由于JavaScript不支持類靠汁,可以用函數(shù)代替,這個(gè)函數(shù)封裝了特定接口創(chuàng)建對象的細(xì)節(jié)闽铐。

function createPerson(name, age, job){
    var i=0;
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function () {
        return name;
    };
    return o;
}

var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

這樣可以快速地創(chuàng)建相似對象蝶怔,但是用這種方法創(chuàng)建的所有對象都是Object類,也就是你無法分辨它們的類型兄墅。

function createDog(name, age, owner){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.owner = owner;
    o.sayName = function () {
        return name;
    };
    return o;
}

var dog = createDog("hali", 2, "Nicholas");
console.log(typeof dog == typeof person1); //true

我覺得你一定不希望狗和你屬于同一個(gè)類型踢星。

構(gòu)造函數(shù)模式

構(gòu)造函數(shù)是很多擁有class的編程語言的做法。

我們希望隙咸,使用JavaScript也能實(shí)現(xiàn)構(gòu)造函數(shù)沐悦。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        console.log(this.name);
    };
}

let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
console.log(typeof person1); //Person

現(xiàn)在,你創(chuàng)建的類終于有了和函數(shù)同名的類型了扎瓶。

這個(gè)函數(shù)沒有返回值所踊,并且和很多編程語言一樣,使用了new來創(chuàng)建對象概荷。

任何函數(shù)秕岛,只要使用了new來創(chuàng)建,那么就是構(gòu)造函數(shù)误证,構(gòu)造函數(shù)本質(zhì)上也是函數(shù)继薛。

但依然有一個(gè)問題,同一個(gè)類之間無法實(shí)現(xiàn)代碼的共用愈捅。

比如sayName需要被創(chuàng)建兩次遏考,第一次在創(chuàng)建person1時(shí),第二次在創(chuàng)建person2時(shí)蓝谨。浪費(fèi)了很多空間灌具。

如何實(shí)現(xiàn)公用呢青团?

原型模式

原型(prototype)是JavaScript很重要的一個(gè)概念。

原型模式使得對象實(shí)例可以共享屬性和方法咖楣。

function Person(){
}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    console.log(this.name);
};

var person1 = new Person();
var person2 = new Person();
console.log(person1.sayName() == person2.sayName()); //true

對象的原型是一個(gè)什么概念呢督笆?

在這里插入圖片描述

Person有一個(gè)Prototype,指向Person的原型诱贿,原型是另外一個(gè)對象娃肿。
當(dāng)JavaScript需要訪問屬性時(shí),首先在Person找珠十,如果沒找到就回去Prototype指向的地方找料扰。

原型中還會(huì)存儲(chǔ)構(gòu)造器constructor,指向Person焙蹭,這幅圖里沒有明示出來晒杈,你也需要知道。

console.log(Person.prototype.constructor) //Person

但是這種方式無法讓Person擁有獨(dú)立的變量壳嚎,也就是說桐智,person1person2都在使用同一個(gè)Prototype指向的對象歉甚,那么當(dāng)person1試圖改變name的時(shí)候奥秆,person2的name也會(huì)變刘绣。

一種解決方法是屏蔽。

person1.name = "Greg";
console.log(person1.name); //Greg

只要為person1重新定義name屬性郑趁,就能屏蔽原型的屬性,因?yàn)橹罢f過姿搜,搜索變量是從構(gòu)造函數(shù)開始的寡润,如果在構(gòu)造函數(shù)中找到了變量也就不會(huì)去原型中搜索。

另外舅柜,我們還能用對象字面量來簡寫原型的定義梭纹。

比如上面的可以這樣寫:

Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function(){
        console.log(this.name);
    }
};

構(gòu)造函數(shù)和原型混成模式

既然如此,干脆把一些屬性在構(gòu)造函數(shù)中定義致份,一些在原型中定義好了变抽。

這也是我們一般推薦的。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
}

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

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

混成模式雖然很好氮块,但是需要把Person和Person.prototype定義分開寫绍载,可能會(huì)遭到一些oo使用者的反對,我們提出一個(gè)更好的模式滔蝉。

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

先用一個(gè)if判斷是否已經(jīng)存在了击儡,是為了防止重載導(dǎo)致的屏蔽行為。

到這一步為止蝠引,終于我們把所有都在Person構(gòu)造函數(shù)內(nèi)完成了阳谍。

寄生構(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(name);
    };

    return o;
}

var person1 = new Person("Nicholas", 29, "Software Engineer");
person1.sayName(); //Nicholas

通過new可以看出我們使用了構(gòu)造函數(shù)蛀柴,但有點(diǎn)奇怪的是,我們依然返回了一個(gè)對象矫夯。

其實(shí)這個(gè)對象把構(gòu)造函數(shù)創(chuàng)建的對象覆蓋掉了名扛。

這個(gè)方法創(chuàng)建的對象類型也是不能分辨的。

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

雖然我們實(shí)現(xiàn)了共用的屬性和方法茧痒,還實(shí)現(xiàn)了對象自己的屬性和方法肮韧,但擺在我們面前最大的問題是訪問權(quán)限,根據(jù)面向?qū)ο蟮脑O(shè)計(jì)原則旺订,實(shí)例對象的屬性不應(yīng)當(dāng)能直接訪問弄企。

根據(jù)這個(gè),設(shè)計(jì)了一種叫穩(wěn)妥構(gòu)造函數(shù)模式的方法去創(chuàng)建對象区拳。

function Person(name, age, job){
    var o = new Object();

    o.sayName = function () {
        console.log(name);
    };

    return o;
}

var person1 = Person("Nicholas", 29, "Software Engineer");
person1.sayName(); //Nicholas

無法直接訪問name拘领,但可以通過函數(shù)訪問。

但這個(gè)方法無法查看對象的類型樱调。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末约素,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笆凌,更是在濱河造成了極大的恐慌圣猎,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乞而,死亡現(xiàn)場離奇詭異送悔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)爪模,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門欠啤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屋灌,你說我怎么就攤上這事洁段。” “怎么了共郭?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵祠丝,是天一觀的道長。 經(jīng)常有香客問我落塑,道長纽疟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任憾赁,我火速辦了婚禮污朽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘龙考。我一直安慰自己蟆肆,他們只是感情好矾睦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著炎功,像睡著了一般枚冗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛇损,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天赁温,我揣著相機(jī)與錄音,去河邊找鬼淤齐。 笑死股囊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的更啄。 我是一名探鬼主播稚疹,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祭务!你這毒婦竟也來了内狗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤义锥,失蹤者是張志新(化名)和其女友劉穎柳沙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缨该,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡偎行,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贰拿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡熄云,死狀恐怖膨更,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缴允,我是刑警寧澤荚守,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站练般,受9級(jí)特大地震影響矗漾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜薄料,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一敞贡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摄职,春花似錦誊役、人聲如沸获列。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽击孩。三九已至,卻和暖如春鹏漆,著一層夾襖步出監(jiān)牢的瞬間巩梢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工艺玲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留括蝠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓板驳,卻偏偏與公主長得像又跛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子若治,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容