JS創(chuàng)建對象的幾種方式

JS創(chuàng)建對象的幾種方式

一. 直接創(chuàng)建Object實例

方式一:

var person = new Object();
person.name = 'zzx';
person.age = 20;
person.job = 'Programmer';

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

方式二:

var person = {
    name: 'zzx';
    age: 20;
    job: 'Programmer';
    
    sayName: function(){
        console.log(this.name);
    }
}

這種方式的缺點顯而易見,每次創(chuàng)建一個對象就需要手動設置它的每一個屬性囱稽,造成大量代碼重復,JS可以使用工廠模式的變體解決這個問題

二. 工廠模式

function createPerson(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 person1 = createPerson('zzx', 22, 'Programmer');
var person2 = createPerson('yzy', 20, 'Teacher');

console.log(person1);
//{ name: 'zzx', age: 20, job: 'Programmer', sayName: [Function] }

這種模式解決了創(chuàng)建多個相似對象的問題,但是卻不知道當前創(chuàng)建的對象是什么類型傻丝,即是Person還是Robot不能判斷出來

三. 構造函數(shù)模式

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

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

var person1 = new Person('zzx', 22, 'Programmer');
var person2 = new Person('yzy', 20, 'Teacher');

console.log(person1 instanceof Person); //true
console.log(person2 instanceof Robot); //false

構造函數(shù)名開頭大寫借鑒了其他面向?qū)ο笳Z言,是為了區(qū)別普通函數(shù)诉儒。任何一個函數(shù)不通過new操作符調(diào)用葡缰,就是一個普通函數(shù):

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

Person('zzx', 22, 'Programmer');
sayName(); //zzx

構造函數(shù)仍然存在缺點,就是其中的每個方法例如sayName()忱反,在每次實例化時都會自動重新創(chuàng)建一遍泛释,產(chǎn)生不同的作用域鏈,因此即使是同名函數(shù)也是不相等的温算,下面利用上述代碼創(chuàng)建兩個實例:

var person1 = new Person('zzx', 22, 'Programmer');
var person2 = new Person('yzy', 20, 'Teacher');

console.log(person1.sayName == person2.sayName); //flase

四. 原型模式

使用原型對象的好處是可以讓所有對象實例共享它所包含的屬性和方法怜校。

function Person(){
}

Person.prototype.name = 'zzx';
Person.prototype.age = 22;
Person.prototype.job = 'Programmer';
Person.prototype.sayName = function(){
    console.log(this.name);
}

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

這里將sayName()方法和所有的屬性直接添加到了Person 的prototype屬性中,構造函數(shù)就成了空函數(shù)注竿,但是也能調(diào)用構造函數(shù)創(chuàng)建新對象茄茁。新隊先后的屬性和方法是所有實例共享的,person1和person2訪問的都是同一組屬性和同一個sayName()函數(shù)巩割。


要理解原型模式工作原理裙顽,先要理解原型對象。

[原型對象]http://www.reibang.com/p/b958bfd92a41


上述方式每添加一個屬性和方法都要輸入Person.prototype宣谈,因此還有更簡單的方式是以對象字面量形式創(chuàng)建:

function Person(){
}

Person.prototype = {
    name: 'zzx',
    age: '22',
    job: 'Programmer',
    sayName: function(){
        console.log(this.name);
    }
};

var person1 = new Person();
console.log(person1 instanceof Person); //true
console.log(person1.constrcutor == Person); //false

但這里使用的語法本質(zhì)上完全重寫了默認的prototype對象(原型對象)愈犹,因此本來會自動獲得的constructor屬性變成了新對象的constructor屬性(指向Object構造函數(shù)),不再指向Person函數(shù)闻丑,此時instanceof能返回正確的結果漩怎,但是constructor已經(jīng)無法確定對象類型了

如果constructor值真的很重要,可以通過下面這樣特意將它設置回適當?shù)闹?/p>

function Person(){
}

Person.prototype = {
    constructor: Person,
    name: 'zzx',
    age: '22',
    job: 'Programmer',
    sayName: function(){
        console.log(this.name);
    }
};

原型模式也有缺點嗦嗡,當其中包含引用類型值屬性時會出現(xiàn)問題:

function Person(){
}

Person.prototype = {
    constructor: Person,
    name: 'zzx',
    age: '22',
    job: 'Programmer',
    friends: ['wc', 'rt'],
    sayName: function(){
        console.log(this.name);
    }
};

var person1 = new Person();
var person2 = new Person();

person1.friends.push('lol');
console.log(person1.friends); //[ 'wc', 'rt', 'lol' ]
console.log(person2.friends); //[ 'wc', 'rt', 'lol' ]

由于數(shù)組存在于Person.prototype中勋锤,當向數(shù)組中添加了一個字符串時,所有的實例都會共享這個數(shù)組(基本值可以被實例屏蔽)

五. 組合使用構造函數(shù)模式和原型模式

創(chuàng)建自定義類型的常見方式侥祭,就是組合使用構造函數(shù)模式與原型模式叁执。構造函數(shù)模式用于定義實例屬性,而原型模式用于定義方法和共享的屬性卑硫。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ['wc', 'rt'];
}

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

六. 動態(tài)原型模式

這里只在 sayName()方法不存在的情況下徒恋,才會將它添加到原型中。

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);
        };
    }
}

var person1 = new Person('zzx', 22, 'Programmer');
person1.sayName();

七. 寄生構造函數(shù)模式

這種模式的基本思想是創(chuàng)建一個函數(shù)欢伏,該函數(shù)的作用僅僅是封裝創(chuàng)建對象的代碼入挣,然后再返回新創(chuàng)建的對象;但從表面上看硝拧,這個函數(shù)又很像是典型的構造函數(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 person1 = new Person('zzx', 22, 'Programmer');
person1.sayName();

這個例子中葛假,除了使用 new 操作符并把使用的包裝函數(shù)叫做構造函數(shù)之外,這個模式跟工廠模式其實是一模一樣的滋恬。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聊训,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恢氯,更是在濱河造成了極大的恐慌带斑,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勋拟,死亡現(xiàn)場離奇詭異勋磕,居然都是意外死亡,警方通過查閱死者的電腦和手機敢靡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門挂滓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啸胧,你說我怎么就攤上這事赶站。” “怎么了纺念?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵贝椿,是天一觀的道長。 經(jīng)常有香客問我柠辞,道長团秽,這世上最難降的妖魔是什么主胧? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任叭首,我火速辦了婚禮,結果婚禮上踪栋,老公的妹妹穿的比我還像新娘焙格。我一直安慰自己,他們只是感情好夷都,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布眷唉。 她就那樣靜靜地躺著,像睡著了一般囤官。 火紅的嫁衣襯著肌膚如雪冬阳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天党饮,我揣著相機與錄音肝陪,去河邊找鬼。 笑死刑顺,一個胖子當著我的面吹牛氯窍,可吹牛的內(nèi)容都是我干的饲常。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狼讨,長吁一口氣:“原來是場噩夢啊……” “哼贝淤!你這毒婦竟也來了?” 一聲冷哼從身側響起政供,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤播聪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后布隔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犬耻,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年执泰,在試婚紗的時候發(fā)現(xiàn)自己被綠了枕磁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡术吝,死狀恐怖计济,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情排苍,我是刑警寧澤沦寂,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站淘衙,受9級特大地震影響传藏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彤守,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一毯侦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧具垫,春花似錦侈离、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至起宽,卻和暖如春洲胖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坯沪。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工绿映, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屏箍。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓绘梦,卻偏偏與公主長得像橘忱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子卸奉,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355