對象創(chuàng)建模式

一晨逝、工廠模式

工廠模式解決了創(chuàng)建多個相似對象的問題犁享,但卻沒有解決對象識別的問題——即知道一個對象的類型

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

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

二胎撤、構(gòu)造函數(shù)模式

function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function () {
          alert(this.name);
        };
      }
      var person1 = new Person("Nicholas", 29, "Software Engineer");
      var person2 = new Person("Greg", 27, "Doctor");

2.1 和工廠函數(shù)的區(qū)別:

  1. 沒有顯示的創(chuàng)建對象
  2. 直接將屬性和方法賦給了this對象
  3. 沒有return語句
  4. 函數(shù)名首字母大寫

創(chuàng)建Person的新實(shí)例恤批,必須用new操作符。以這種方式調(diào)用構(gòu)造函數(shù)實(shí)際上會經(jīng)歷以下4個步驟:

  1. 創(chuàng)建一個新對象
  2. 將構(gòu)造函數(shù)的作用域賦值給新對象(因此this就指向了這個新對象)
  3. 執(zhí)行這個構(gòu)造函數(shù)中的代碼(為這個新對象添加屬性)
  4. 返回新對象

這里例子中person1person2分別保存著Person的一個不同的實(shí)例唱凯。這兩個對象都有一個constructor(構(gòu)造函數(shù))屬性,該屬性指向Person

alert(person1.constructor == Person) // true
alert(person2.constructor == Person) // true

對象的constructor屬性最初是用來標(biāo)識對象類型的谎痢。但是檢測對象類型磕昼,還是instanceof更可靠。

創(chuàng)建自定義的構(gòu)造函數(shù)意味著將來可以將它的實(shí)例標(biāo)識為一種特定的類型节猿。這正是構(gòu)造函數(shù)勝過工廠模式的地方票从。

2.2 構(gòu)造函數(shù)和普通函數(shù)的區(qū)別

構(gòu)造函數(shù)和其他函數(shù)唯一的區(qū)別漫雕,就在于調(diào)用它們的方式不同。任何函數(shù)峰鄙,只要通過new操作符調(diào)用浸间,那它就可以作為構(gòu)造函數(shù);而任何函數(shù)吟榴,如果不通過new操作符來調(diào)用魁蒜,那它和普通函數(shù)也不會有什么兩樣。

// 當(dāng)做構(gòu)造函數(shù)使用
var person = new Person("Nicholas",29,"Software Engineer")
person.sayName(); //"Nicholas"

// 作為普通函數(shù)調(diào)用
Person("Greg",27,"Doctor") // 添加到window
window.sayName(); //"Greg"

// 在另一個對象的作用域中調(diào)用
var o = new Object();
Person.call(o,"Kristen",25,"Nurse")
o.sayName();  //"Kristen"

2.3 構(gòu)造函數(shù)的問題

每個方法都要在每個實(shí)例上重新創(chuàng)建一遍吩翻《悼矗可以通過在全局作用域中創(chuàng)建函數(shù)解決這一問題,但這樣讓引用類型沒有封裝性狭瞎。

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

 function sayName() {
   alert(this.name);
 }
 var person1 = new Person("Nicholas", 29, "Software Engineer");
 var person2 = new Person("Greg", 27, "Doctor");
 console.log(person1, person2);

三铣减、原型模式

我們創(chuàng)建的每個函數(shù)都有一個`prototype`(原型)屬性,這個屬性是一個指針脚作,這個對象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法葫哗。使用原型的好處是可以讓所有對象實(shí)例共享它包含的屬性和方法。
function Person() {}

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

var person1 = new Person();
person1.sayName();

var person2 = new Person();
person2.sayName();

alert(person1.sayName == person2.sayName);

3.1 理解原型對象

無論什么時候球涛,只要創(chuàng)建了一個新函數(shù)劣针,就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個prototype屬性,這個屬性指向函數(shù)的原型對象亿扁。在默認(rèn)情況下捺典,所有原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針从祝。

  1. 原型對象的缺點(diǎn)
    原型中所有屬性是被很多實(shí)例共享襟己,這種共享對于函數(shù)非常合適。對于包含基本值的屬性也可以牍陌,對于包含引用類型的屬性來說擎浴,可能會被修改。
function Person() {}

Person.prototype = {
  constructor: Person,
  name: "Nicholas",
  age: 29,
  job: "Software Engineer",
  friends: ["Shelby", "Court"],
  sayName: function () {
    alert(this.name);
  },
};

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

person1.friends.push("Van");

alert(person1.friends); // "Shelby,Court,Van"
alert(person2.friends); // "Shelby,Court,Van"
alert(person1.friends === person2.friends); // true

四毒涧、組合使用構(gòu)造函數(shù)模式和原型模式

構(gòu)造函數(shù)模式用于定義實(shí)例屬性贮预,而原型模式用于定義方法和共享的屬性。結(jié)果每個實(shí)例都會有自己的一份實(shí)例屬性的副本契讲,但同時又共享者對方付的引用仿吞,最大限度地節(jié)省了內(nèi)存。

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

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

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

person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); // "Shelby,Court"
alert(person1.friends === person2.friends); // false
alert(person1.sayName === person2.sayName); // true

五捡偏、動態(tài)原型模式

可以將所有信息封裝在構(gòu)造函數(shù)中唤冈。

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

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

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

使用動態(tài)模式時,不能使用對象字面量重寫原型银伟。如果在已經(jīng)創(chuàng)建了實(shí)例的情況下重寫原型你虹,那么就會切斷現(xiàn)有實(shí)例與新實(shí)例之間的聯(lián)系

六凉当、寄生構(gòu)造函數(shù)模式

通常,在前述幾種模式都不適用的情況下售葡,可以使用寄生構(gòu)造函數(shù)模式看杭。這種模式的基本思想是創(chuàng)建一個函數(shù),該函數(shù)的作用僅僅是封裝創(chuàng)建對象的代碼挟伙,然后再返回新創(chuàng)建的對象楼雹;

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

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

例如:

function SpecialArray() {
  // 創(chuàng)建數(shù)組
  var values = new Array();

  //添加值
  values.push.apply(values, arguments);

  //添加方法
  values.toPipedString = function () {
    return this.join("|");
  };

  //返回數(shù)組
  return values;
}

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

返回的對象與在構(gòu)造函數(shù)外部創(chuàng)建的對象沒什么不同

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

所謂穩(wěn)妥對象尖阔,指的是沒有公共屬性贮缅,而且其方法也不引用this的對象。

與寄生構(gòu)造函數(shù)的區(qū)別:

  1. 創(chuàng)建對象的實(shí)例方法不引用this
  2. 不使用new操作符調(diào)用構(gòu)造函數(shù)
function Person(name, age, job) {
  // 創(chuàng)建要返回的對象
  var o = new Object();

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

  // 返回對象
  return o;
}

var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末介却,一起剝皮案震驚了整個濱河市谴供,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌齿坷,老刑警劉巖桂肌,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異永淌,居然都是意外死亡崎场,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門遂蛀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谭跨,“玉大人,你說我怎么就攤上這事李滴◇χ妫” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵所坯,是天一觀的道長谆扎。 經(jīng)常有香客問我,道長包竹,這世上最難降的妖魔是什么燕酷? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任籍凝,我火速辦了婚禮周瞎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饵蒂。我一直安慰自己声诸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布退盯。 她就那樣靜靜地躺著彼乌,像睡著了一般泻肯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上慰照,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天灶挟,我揣著相機(jī)與錄音,去河邊找鬼毒租。 笑死稚铣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的墅垮。 我是一名探鬼主播惕医,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼算色!你這毒婦竟也來了抬伺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灾梦,失蹤者是張志新(化名)和其女友劉穎峡钓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體若河,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椒楣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了牡肉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捧灰。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖统锤,靈堂內(nèi)的尸體忽然破棺而出毛俏,到底是詐尸還是另有隱情,我是刑警寧澤饲窿,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布煌寇,位于F島的核電站,受9級特大地震影響逾雄,放射性物質(zhì)發(fā)生泄漏阀溶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一鸦泳、第九天 我趴在偏房一處隱蔽的房頂上張望银锻。 院中可真熱鬧,春花似錦做鹰、人聲如沸击纬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽更振。三九已至炕桨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肯腕,已是汗流浹背献宫。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留实撒,地道東北人遵蚜。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像奈惑,于是被迫代替她去往敵國和親吭净。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

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