新手看JS中的面向?qū)ο?/h1>

面向?qū)ο?/h2>

??面向?qū)ο笫且环N程序設(shè)計(jì)的思想撑教,與面向過(guò)程不同叹话,它引入了類(lèi)的概念偷遗,將性質(zhì)相似的一類(lèi)物體抽象出來(lái),作為設(shè)計(jì)圖一般的存在渣刷,以實(shí)體的方式描述業(yè)務(wù)鹦肿,重心放在了參與事務(wù)的對(duì)象身上,而不是逐步分離的步驟上辅柴。
??面向?qū)ο笥腥齻€(gè)特征:封裝箩溃、繼承、多態(tài)碌嘀,關(guān)于繼承涣旨,可以在讀完本文后,去看看我的另一片文章股冗,新手看JS的六張繼承方式霹陡,這里暫且先不多做解釋。

與面向過(guò)程的區(qū)別

??這里借用一下百度知道上某位仁兄的解釋?zhuān)?br> ??例如五子棋游戲,面向過(guò)程的設(shè)計(jì)思路就是首先分析問(wèn)題的步驟:
??1止状、開(kāi)始游戲烹棉,
??2、黑子先走怯疤,
??3浆洗、繪制畫(huà)面,
??4集峦、判斷輸贏(yíng)伏社,
??5、輪到白子塔淤,
??6摘昌、繪制畫(huà)面,
??7高蜂、判斷輸贏(yíng)聪黎,
??8、返回步驟2备恤,
??9挺举、輸出最后結(jié)果。

??把上面每個(gè)步驟用分別的函數(shù)來(lái)實(shí)現(xiàn)烘跺,問(wèn)題就解決了湘纵。

??而面向?qū)ο?/em>的設(shè)計(jì)則是從另外的思路來(lái)解決問(wèn)題。整個(gè)五子棋可以分為 :
??1滤淳、黑白雙方梧喷,這兩方的行為是一模一樣的,
??2脖咐、棋盤(pán)系統(tǒng)铺敌,負(fù)責(zé)繪制畫(huà)面,
??3屁擅、規(guī)則系統(tǒng)偿凭,負(fù)責(zé)判定諸如犯規(guī)、輸贏(yíng)等派歌。

??第一類(lèi)對(duì)象(玩家對(duì)象)負(fù)責(zé)接受用戶(hù)輸入弯囊,并告知第二類(lèi)對(duì)象(棋盤(pán)對(duì)象)棋子布局的變化痰哨,棋盤(pán)對(duì)象接收到了棋子的i變化就要負(fù)責(zé)在屏幕上面顯示出這種變化,同時(shí)利用第三類(lèi)對(duì)象(規(guī)則系統(tǒng))來(lái)對(duì)棋局進(jìn)行判定匾嘱。
??以上斤斧,兩種模式的區(qū)別,由此可見(jiàn)一斑霎烙。

JS中的對(duì)象

??JS是解釋性的腳本語(yǔ)言撬讽,對(duì)于類(lèi)的概念并沒(méi)有JAVA那般嚴(yán)謹(jǐn)和規(guī)范,且擁有自己的特性和方法悬垃。
??創(chuàng)建對(duì)象的過(guò)程游昼,便是畫(huà)一份設(shè)計(jì)圖,JS一共提供了 7 種創(chuàng)建的方式(來(lái)自高程三)尝蠕,包括:
??1.工廠(chǎng)模式
??2.構(gòu)造函數(shù)模式
??3.原型模式
??4.組合使用構(gòu)造函數(shù)模式和原型模式
??5.動(dòng)態(tài)原型模式
??6.寄生構(gòu)造函數(shù)模式
??7.穩(wěn)妥構(gòu)造函數(shù)模式
??其中使用最廣泛烘豌、認(rèn)同度最高的方式是第四種:組合使用構(gòu)造函數(shù)模式和原型模式,下面對(duì)每種方式進(jìn)行粗略的描述趟佃。

創(chuàng)建對(duì)象

1.工廠(chǎng)模式

function createPerson(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        alert(this.name)
    };
    return o;
}
var person = createPerson("亞當(dāng)",99);

??接收兩個(gè)參數(shù)扇谣,在函數(shù)內(nèi)部創(chuàng)建一個(gè)對(duì)象,然后將參數(shù)綁定后再返回闲昭,可以實(shí)現(xiàn)封裝一個(gè)類(lèi)的功能罐寨,但缺點(diǎn)是所有的對(duì)象的都是Object,無(wú)法準(zhǔn)確判斷它們的類(lèi)型序矩,比如“人”類(lèi)是Object鸯绿,“動(dòng)物”類(lèi)也是Object。
??于是出現(xiàn)了構(gòu)造函數(shù)模式簸淀。

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

function Person(name,age){    //注意:首字母大寫(xiě)(慣例)
    this.name = name;
    this.age = age;
    this.sayName = function(){
        alert(this.name)
    };
}
var person = new Person("亞當(dāng)",99);

??不用return對(duì)象瓶蝴,將屬性和方法直接給了this對(duì)象,這樣便可以用alert(person instanceof Person);//ture來(lái)檢測(cè)對(duì)象的類(lèi)型租幕,這意味著將來(lái)可以將Person標(biāo)識(shí)為一種特定的類(lèi)型舷手,更利于類(lèi)的概念。
??有了“類(lèi)”的模板劲绪,就可以照著模子捏人了男窟,使用構(gòu)造函數(shù)創(chuàng)建對(duì)象,必須使用到new操作符贾富,若是當(dāng)做普通函數(shù)來(lái)使用歉眷,就相當(dāng)是為全局對(duì)象添加了屬性,最后會(huì)出現(xiàn)window.sayName();//打印出傳入的name變量颤枪,而使用new來(lái)調(diào)用構(gòu)造函數(shù)會(huì)經(jīng)歷一下四個(gè)步驟:
??1.創(chuàng)建一個(gè)新對(duì)象
??2.將構(gòu)造函數(shù)的作用域賦給新對(duì)象
??3.執(zhí)行構(gòu)造函數(shù)中的代碼(為新對(duì)象添加屬性)
??4.返回這個(gè)新對(duì)象
??構(gòu)造函數(shù)模式同樣有其缺陷汗捡,比如上面的例子中,如果創(chuàng)建了兩個(gè)“人”畏纲,就有兩個(gè)同樣的sayName()方法扇住,可以實(shí)現(xiàn)同樣的功能(打印名字)春缕,一個(gè)兩個(gè)還好,如果我們有成百上千個(gè)Person實(shí)例的話(huà)台囱,name就有千百個(gè)satName()方法淡溯,這在內(nèi)存中的開(kāi)銷(xiāo)無(wú)疑是極大的读整,既然是同樣的功能簿训,那么讓它們共同使用一個(gè)函數(shù)就足夠了,因此可以將這個(gè)函數(shù)摘出來(lái)米间,這樣寫(xiě):

function Person(name,age){    //注意:首字母大寫(xiě)(慣例)
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
}

??將內(nèi)部引用外部命名的函數(shù)强品,而將函數(shù)體放在外面,這樣指向的就是同一個(gè)方法了屈糊,只是如此一來(lái)sayName這個(gè)方法相當(dāng)于是放在了全局作用域中的榛,但方法本身卻只想讓Person的對(duì)象使用,大炮打蚊子逻锐,有點(diǎn)小尷尬夫晌,同時(shí)類(lèi)的封裝性也遭到了破壞,由此問(wèn)題昧诱,便引出了第三種創(chuàng)建方法——原型模式晓淀。

3.原型模式

??每個(gè)構(gòu)造函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針盏档,指向一個(gè)對(duì)象凶掰,而這個(gè)對(duì)象的用途,便是容納同一類(lèi)下所有實(shí)例公有的方法和屬性蜈亩,寫(xiě)法如下懦窘。

function Person(){
}
Person.prototype.name = "亞當(dāng)";
Person.prototype.age = "99";
Person.prototype.sayName= function(){
    alert(this.name)
};
var person = new Person();

??或者寫(xiě)的更簡(jiǎn)潔一些:

Person.prototype = {
    name : "亞當(dāng)",
    age : "99",
    sayName : function(){
        alert(this.name);
    }
}

??好處很明顯,同一類(lèi)下所有對(duì)象可以共享屬性和方法稚配,當(dāng)然畅涂,缺點(diǎn)一樣明顯,創(chuàng)建對(duì)象的時(shí)候無(wú)法傳入自定義參數(shù)道川,除非設(shè)置如person1.name = "夏娃";才會(huì)覆蓋掉原來(lái)的名字午衰,更為嚴(yán)重的是,如果Person的原型中包含了一個(gè)數(shù)組(引用類(lèi)型)愤惰,如果一個(gè)對(duì)象修改了這個(gè)數(shù)組苇经,其他對(duì)象的數(shù)組都會(huì)發(fā)生變化,因?yàn)橐妙?lèi)型的變量指向的是同一塊內(nèi)存地址宦言,這樣事情就變得很麻煩了扇单。
??構(gòu)造函數(shù)模式無(wú)法設(shè)置共享的屬性,而原型模式無(wú)法自定義屬性奠旺,那如果將兩者優(yōu)點(diǎn)結(jié)合起來(lái)蜘澜,那不是天下無(wú)敵了嗎J┝鳌?
??所以鄙信,我們有了第四種方式——組合使用構(gòu)造函數(shù)模式和原型模式瞪醋。

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

??不多說(shuō),直接上代碼:

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype = {
    constructor : Person,    //確保實(shí)例的構(gòu)造函數(shù)指向Person
    sayName : function(){
        alert(this.name);
    }
}
var person = new Person("亞當(dāng)",99);

??可以自定義的屬性(包括引用類(lèi)型)都放在構(gòu)造函數(shù)里装诡,隨便修改都不會(huì)影響其他實(shí)例银受,而公共的方法則放在原型對(duì)象中,避免資源浪費(fèi)鸦采。
??OJBK宾巍,萬(wàn)事大吉!這種模式也是目前在ECMAScript中使用最廣泛渔伯、認(rèn)同度最高的一種創(chuàng)建自定義的方法顶霞。
??至此,基本的幾種已經(jīng)介紹完了锣吼,后面三種會(huì)簡(jiǎn)單介紹一下选浑,不想繼續(xù)深入的小伙伴們可以在這里搬小板凳撤了


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

??當(dāng)我們?yōu)閷?duì)象定義一個(gè)方法時(shí),有時(shí)可能存在沖突玄叠,必要的情況下古徒,我們可以檢查某個(gè)應(yīng)該存在的方法是否有效,如果有效诸典,看一眼走人描函,如果無(wú)效,我們?cè)俪跏蓟汀?/p>

function Person(name,age){
    this.name = name;
    this.age = age;
}
//方法
if(typeof this.sayName != "function"){    //如果sayName不是函數(shù)
    Person.prototype.sayName= function(){
        alert(this.name)
    }
};

??如上述代碼狐粱,僅當(dāng)sayName方法不存在的情況下舀寓,才會(huì)在原型中添加此方法,而且只會(huì)在初次調(diào)用構(gòu)造函數(shù)的時(shí)候才會(huì)執(zhí)行這條語(yǔ)句肌蜻,一旦定義后互墓,由于是定義在原型上的方法,所有對(duì)象之后都可以直接調(diào)用了蒋搜。
??這種方法的缺陷篡撵,同樣是不能重寫(xiě)原型,否則會(huì)切斷現(xiàn)有實(shí)例與心源性之間的聯(lián)系豆挽。

6.寄生構(gòu)造函數(shù)模式

??唔...在前面幾種模式都不適用的情況下(應(yīng)該不會(huì)遇到吧...)育谬,可以使用寄生構(gòu)造函數(shù)模式創(chuàng)建對(duì)象,基本思想是:創(chuàng)建一個(gè)函數(shù)帮哈,其作用僅僅只是封裝創(chuàng)建對(duì)象的代碼膛檀,然后再返回新創(chuàng)建的對(duì)象。

function Person(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        alert(this.name)
    };
    return o;
}
var person = new Person("亞當(dāng)",99);

??除了用new操作符以外,其余寫(xiě)法和工廠(chǎng)模式一模一樣咖刃,一般會(huì)在特殊情況下使用它泳炉,例如要?jiǎng)?chuàng)建一個(gè)數(shù)組對(duì)象(Array),但在這個(gè)對(duì)象中要添加新的方法嚎杨,直接修改Array的構(gòu)造函數(shù)的話(huà)花鹅,程序里所有的數(shù)組都變了,GG枫浙,所以可以使用這個(gè)模式刨肃。代碼如下:

function specialArray(){
    var arr = new Array();
    arr.newFunction = function(){
        alert("我叫數(shù)組的新方法")
    }
    balabalabala...  //其他要添加的新方法或操作
    return arr;
}
var list = new specialArray();
list.newFunction();  //我叫數(shù)組的新方法 

??要注意,返回的對(duì)象與構(gòu)造函數(shù)之間沒(méi)有關(guān)系自脯,不能使用instanceof來(lái)確定對(duì)象類(lèi)型之景,這一點(diǎn)與工廠(chǎng)模式相同斤富,因此建議盡可能不要使用這種方法膏潮。

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

??穩(wěn)妥對(duì)象,指的是沒(méi)有公共屬性满力,也不引用this對(duì)象焕参,這種模式適合在禁止使用 this 和 new 的環(huán)境中,或者在防止數(shù)據(jù)被其他應(yīng)用程序(如Mashup程序)改動(dòng)時(shí)使用油额,除了不使用 this 和 new 以外叠纷,和寄生構(gòu)造函數(shù)模式類(lèi)似,代碼如下:

function Person(name,age){
    var o = new Object();
    //可以在這里定義私有變量和屬性
    o.sayName = function(){
        alert(name)
    };
    return o;
}
var person = Person("亞當(dāng)",99);
person.sayName();    //亞當(dāng)

??除了使用sayName() 方法外潦嘶,沒(méi)有其他辦法訪(fǎng)問(wèn) name 的值涩嚣,方法中定義的私有變量和屬性也無(wú)法影響傳入的 name 值,安全性杠杠的掂僵!
??當(dāng)然航厚,與寄生構(gòu)造函數(shù)模式、工廠(chǎng)模式相同锰蓬,它也不能使用 instanceof 檢測(cè)其類(lèi)型幔睬。

總結(jié)

??至此,JS面向?qū)ο笈c其中創(chuàng)建方法基本結(jié)束了芹扭,如文章有問(wèn)題麻顶,歡迎指正!2湛ā辅肾!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轮锥,隨后出現(xiàn)的幾起案子矫钓,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件份汗,死亡現(xiàn)場(chǎng)離奇詭異盈电,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杯活,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)匆帚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人旁钧,你說(shuō)我怎么就攤上這事吸重。” “怎么了歪今?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵嚎幸,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寄猩,道長(zhǎng)嫉晶,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任田篇,我火速辦了婚禮替废,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泊柬。我一直安慰自己椎镣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布兽赁。 她就那樣靜靜地躺著状答,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刀崖。 梳的紋絲不亂的頭發(fā)上惊科,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音蒲跨,去河邊找鬼译断。 笑死,一個(gè)胖子當(dāng)著我的面吹牛或悲,可吹牛的內(nèi)容都是我干的孙咪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼巡语,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼翎蹈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起男公,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荤堪,失蹤者是張志新(化名)和其女友劉穎合陵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澄阳,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拥知,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碎赢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片低剔。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肮塞,靈堂內(nèi)的尸體忽然破棺而出襟齿,到底是詐尸還是另有隱情,我是刑警寧澤枕赵,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布猜欺,位于F島的核電站,受9級(jí)特大地震影響拷窜,放射性物質(zhì)發(fā)生泄漏开皿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一装黑、第九天 我趴在偏房一處隱蔽的房頂上張望副瀑。 院中可真熱鬧,春花似錦恋谭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至信认,卻和暖如春材义,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嫁赏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工其掂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人潦蝇。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓款熬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親攘乒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贤牛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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