摘要:北山愚公者年且九十面山而居。工廠模式愚小公北山愚小小公北山工廠模式比較明顯的一個缺點就是由于生成并返回了一個中間對象,所以不能判斷對象的類型。
??太行、王屋二山,方七百里,高萬仞。本在冀州之南,河陽之北.......
??嗯,按照慣例,第一句話就是騙你們點進(jìn)來的。在讀本文之前,希望你對Javascript的原型和原型鏈有一定了解,這有助于你更好的理解本文,之前有寫過一篇相關(guān)文章,點此閱讀。但這并不是必須的。
??都退后,我要繼續(xù)講故事了。
??北山愚公者,年且九十,面山而居。
var person = { name : "愚公", age: 90, address: "北山腳下", whereToLive: function () { alert(this.address) } };
??......北山愚公曰:“雖我之死,有子存焉;子又生孫,孫又生子;子又有子,子又有孫;子子孫孫無窮匱也”。
??看到這兒,問題來了,愚公的子子孫孫那么多,顯然使用對象字面量去創(chuàng)建是不合理的。我們介紹第一種創(chuàng)建方式。
工廠模式function createPerson (name, age, address){ var o = new Object(); o.name = name; o.age = age; o.address = address; o.whereToLive = function () { alert(this.address) }; return o; } var son = createPerson("愚小公", 30, "北山"); var grandSon = createPerson("愚小小公", 5, "北山");
??工廠模式比較明顯的一個缺點就是由于生成并返回了一個中間對象,所以不能判斷對象的類型。
構(gòu)造函數(shù)模式function Person(name, age, address) { this.name = name; this.age = age; this.address = address; this.whereToLive = function(){ alert(this.address); }; } var son = new Person("愚小公", 30, "北山"); var grandSon = new Person("愚小小公", 5, "北山");
??構(gòu)造函數(shù)與普通函數(shù)沒有異處,沒有語法上的任何差別,只是在調(diào)用的時候使用了new關(guān)鍵字。所以我們有必要說一下new到底干了什么:
創(chuàng)建一個新的中間對象
將構(gòu)造函數(shù)的作用于賦給這個中間對象
執(zhí)行構(gòu)造函數(shù)中的代碼
返回中間對象
??以這里的代碼為例,實際上第二步和第三步的操作可以總結(jié)為Person.apply(newObject,arguments),這里順便說一句bind與call/apply的一個區(qū)別,bind返回的是一個函數(shù),call/apply是順帶把這個函數(shù)給執(zhí)行了,返回的是執(zhí)行后的結(jié)果。
??那么,構(gòu)造函數(shù)模式有什么問題呢,其實也是顯而易見的,如果愚公有一千個子子孫孫,那么每個子孫都會自帶一個whereToLive的方法,顯然這種做法不文藝范兒
原型模式function Person () { } Person.prototype.name = "愚公"; Person.prototype.age = 90; Person.prototype.address = "北山"; Person.prototype.whereToLive = function () { alert(this.address); }; var son = new Person(); var grandSon = new Person(); son.name = "愚小公"; son.address = "山的那邊"; son.whereToLive(); // "山的那邊" grandSon.whereToLive(); // "北山"
??我們在son對象上試圖修改address屬性,并且似乎看起來也修改成功了,但是沒有影響到grandSon的屬性。所以其實這兩個address其實并不一樣。為什么呢?我們在做如下操作:
delete son.address; son.whereToLive(); // "北山"
??我們刪掉了son的address屬性,這時候son的address又成了原型中定義的值。所以我們在修改address屬性的時候并沒有動到原型中的值,而是在這個對象上新建了一個屬性。并且在試圖獲取這個屬性的時候會優(yōu)先返回對象上的屬性值。我們管這個現(xiàn)象叫屬性屏蔽。
??另外多提一點,就是在讀取對象屬性的時候,首先會查看該對象本身有沒有,沒有的話會順著原型鏈一直向上查找,如果達(dá)到原型鏈頂層都沒有找到,則返回undefined。這里再穿插一個知識點。很多剛?cè)腴T的開發(fā)者會犯這樣的錯誤:
var a = {}; console.log(a.b.c)
??在沒有校驗b屬性是否存在便去試圖獲取c屬性。如果到了原型鏈的頂端都沒有找到b,a.b的值則為undefined,所以獲取undefined的c屬性一定會報錯。正確的做法是在不確定是否存在對應(yīng)屬性的時候,應(yīng)當(dāng)先做判斷。
??但是在寫入基本類型屬性的時候有所不同,在當(dāng)前對象沒有找到要寫入的屬性時,不會向上查找,而是在當(dāng)前對象里新建一個屬性,這么做的原因是防止污染其他對象的屬性值。細(xì)心的你可能發(fā)現(xiàn)了我在開頭的時候強(qiáng)調(diào)了基本類型屬性。如果是引用類型會怎么樣呢?
function Person () { } Person.prototype.name = "愚公"; Person.prototype.age = 90; Person.prototype.address = ["北山"]; Person.prototype.whereToLive = function () { alert(this.address); }; var son = new Person(); var grandSon = new Person(); son.address.push("山的那邊"); grandSon.whereToLive(); // "北山","山的那邊"
??這里又有一個小知識點,引用類型是存在堆內(nèi)存中的,不同地方的應(yīng)用其實指向的是同一塊堆內(nèi)存。所以如果試圖修改原型對象中的應(yīng)用類型,會造成全局污染,這也就是原型模式的一個致命缺點。
組合使用構(gòu)造函數(shù)模式和原型模式??坐穩(wěn),我又要穿插新的知識點了。我們可以采用簡寫的方式避免原型模式賦予原型對象方法時啰嗦的問題。
function Person(name, age, address) { this.name = name; this.age = age; this.address = address; } Person.prototype = { constructor : Person, // 手動修改構(gòu)造函數(shù)指向 whereToLive : function () { alert(this.address); }, howOld : function () { alert(this.age); } }
??組合使用構(gòu)造函數(shù)模式和原型模式的寫法是不是同時規(guī)避掉了構(gòu)造函數(shù)模式和原型模式的問題呢?既可以共享公用的函數(shù),又可以讓每個對象獨享自己的屬性。
??需要注意的是,我們在重寫Person.prototype的時候,實際上使得constructor指向了Object,所以我這里進(jìn)行了手動修正。
寄生構(gòu)造函數(shù)模式function PersonList (name, age, address){ var o = new Array(); o.push.apply(o, arguments); o.consoleString = function () { return this.join(","); }; return o; } var list = new PersonList("愚小公", "愚小小公"); alert(list.consoleString());
??是不是很眼熟,跟工廠模式一模一樣,只不過是在調(diào)用的時候使用了new關(guān)鍵字。利用這種模式,我們可以為對象添加額外的能力。本例中,就是給數(shù)組添加一個自定義的方法,使其可以擁有我們賦予的新能力。
結(jié)語??實際開發(fā)中還是得根據(jù)實際場景靈活運用,總有適合你的那一款。今天就聊到這,歡迎大家補(bǔ)充和指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107955.html
摘要:它是第一個把數(shù)據(jù)分布在全球范圍內(nèi)的系統(tǒng),并且支持外部一致性的分布式事務(wù)。目的是使得開發(fā)者閱讀之后,能對項目有一個初步了解,更好的參與進(jìn)入的開發(fā)中。深度探索數(shù)據(jù)庫并發(fā)控制技術(shù)并發(fā)控制技術(shù)是數(shù)據(jù)庫事務(wù)處理的核心技術(shù)。 存儲過程高級篇 講解了一些存儲過程的高級特性,包括 cursor、schema、控制語句、事務(wù)等。 數(shù)據(jù)庫索引與事務(wù)管理 本篇文章為對數(shù)據(jù)庫知識的查缺補(bǔ)漏,從索引,事務(wù)管理,...
摘要:若函數(shù)不能執(zhí)行有效的轉(zhuǎn)換,返回。如果數(shù)值超過可表示的范圍,則返回或。示例輸入輸出解釋轉(zhuǎn)換截止于數(shù)字,因為它的下一個字符不為數(shù)字。 這是我參與11月更文挑戰(zhàn)的第12天。一、寫在前面LeetCode 第一題兩數(shù)之和傳輸門:聽說你還在寫雙層for循環(huán)解兩數(shù)之和?LeetCode 第二題兩數(shù)之和傳輸門:兩個排序數(shù)組的中...
摘要:據(jù)不完全統(tǒng)計,這五年中,白鷺引擎累計運轉(zhuǎn)的游戲和微信小游戲的流水?dāng)?shù)據(jù)約為億。 我們的引擎架構(gòu)師做某一沙龍活動的演講速記,純純的干貨,分享給大家。 王澤:各位開發(fā)者下午好!我叫王澤,是白鷺引擎的首席架構(gòu)師。 今天給大家分享的題目是《重度H5游戲性能優(yōu)化技巧》。之所以決定用這個題目,是因為我最近幾周在廣深一帶拜訪了很多使用白鷺引擎的開發(fā)者,發(fā)現(xiàn)特別是在廣州一帶,大部分開發(fā)者都在做重度H5游...
javascript是一門弱語言,他有著分同一般的靈活性使它迅速的成為幾乎人人必會的一門語言,but,你們使用的姿勢真的正確嗎? 在以前的開發(fā)過程當(dāng)中,老板:給我加個驗證用戶郵箱、驗證用戶短信...功能! function checkMessage(){...} function checkEmail(){...} function ... //茫茫多的函數(shù) 這樣寫好了之后 function 是全...
閱讀 582·2021-11-22 14:45
閱讀 3070·2021-10-15 09:41
閱讀 1555·2021-10-11 10:58
閱讀 2797·2021-09-04 16:45
閱讀 2605·2021-09-03 10:45
閱讀 3238·2019-08-30 15:53
閱讀 1221·2019-08-29 12:28
閱讀 2133·2019-08-29 12:14