JavaScript面向?qū)ο笈c繼承(2)

面向?qū)ο笾蓄愔傅氖峭活愋蛯ο蟮某橄笾ё樱鬃帜复髮懘锸妫热缜捌械男螤頢hape 類,三角形是通過Shape擴(kuò)展而來昨登,則也是一個類贯底,Shape稱之為它的父類丈甸,它是Shape的子類,同理Rect也是Shape的一個子類睦擂。類的具體抽象稱之為實例顿仇,通常為小寫摆马,創(chuàng)建實例的過程稱之為實例化。上文中triangle就是一個Triangle三角形的實例述呐,指具體畫出的那個三角形蕉毯。關(guān)于父類,子類的實例

  • 父類 Animal
  • 子類 Cat 實例 cat1_tom
  • 子類 Dog 實例 dog1
    Animal 指所有動物进肯,Cat 指所有貓 繼承Animal 是動物的一個子類江掩,cat1_tom 指的具體一個叫 tom 的貓。有了類我們就需要給類加一些標(biāo)識环形,以區(qū)分類之間的區(qū)別抬吟、即屬性和方法。

1. JS原型

弄清楚了類是什么任洞,而JavaScript沒有類的概念发侵,是通過原型來實現(xiàn)面向?qū)ο笕婿T谝灶悶橹行牡拿嫦驅(qū)ο缶幊陶Z言中,類和對象的關(guān)系可以想象成鑄模和鑄件的關(guān)系叔锐,對象總是從類中創(chuàng)建而來愉烙。而在原型編程的思想中,類并不是必需的返顺,對象未必需要從類中創(chuàng)建而來蔓肯,一個對象是通過克隆另外一個對象所得到的。

ES6為了在繼承上與傳統(tǒng)面向?qū)ο笳Z言更加類似秉扑,引入了class调限。
ES5 的繼承,實質(zhì)是先創(chuàng)造子類的實例對象 this吨娜,然后再將父類的方法添加到 this 上面(Parent.apply(this))宦赠。ES6 的繼承機(jī)制完全不同,實質(zhì)是先將父類實例對象的屬性和方法勾扭,加到 this 上面(所以在 constructor 里必須先調(diào)用super方法)妙色,然后再用子類的構(gòu)造函數(shù)修改this。

從設(shè)計模式的角度講丐谋,原型模式是用于創(chuàng)建對象的一種模式煌珊,如果我們想要創(chuàng)建一個對象定庵,一種方法是先指定它的類型,然后通過類來創(chuàng)建這個對象猪落。原型模式選擇了另外一種方式畴博,我們不再關(guān)心對象的具體類型,而是找到一個對象蜜唾,然后通過克隆來創(chuàng)建一個一模一樣的對象。而克隆出來的這個對象會記住他的原型庶艾,由誰克隆而來,同時也會共享原型的屬性和方法擎勘。這樣一個一個對象克隆而來咱揍,則形成了一條原型鏈。對上文中的例子而言棚饵,三角形的原型是形狀煤裙,貓和狗的原型是動物掩完。

2. 構(gòu)造函數(shù)
在js中類之后跟的是一個構(gòu)造函數(shù)。

function Shape(name) {
  this.val = 1;
  this.name = name;
  this.all = '圖形';
  return this.name
}
let a = Shape('a'); // 'a'

let shape1 = new Shape('triangle'); 
let shape2 = new Shape('rect');

構(gòu)造函數(shù)的定義與一般函數(shù)的定義相同硼砰,注意首字母大寫且蓬。構(gòu)造函數(shù)本質(zhì)上還是一個函數(shù),可以傳參可以有返回值题翰,只是內(nèi)部使用了this變量,函數(shù)存在調(diào)用問題:

直接調(diào)用:在瀏覽器環(huán)境中相當(dāng)于在window上掛在了val這個屬性豹障,值為1冯事。請注意這個特點,如果Shape.call(obj) 即相當(dāng)于設(shè)定obj對象的val為1血公。
new 調(diào)用:生成一個實例昵仅,即生成一個新對象,這個this指向當(dāng)前新生成的對象累魔。

constructor和prototype
實例/構(gòu)造函數(shù)(構(gòu)造器)的關(guān)系是
A為B的構(gòu)造函數(shù) 則 B為A的一個實例摔笤。

首先創(chuàng)建一個Cat的構(gòu)造函數(shù),希望say是Cat的實例共享屬性垦写,

function Cat(name) {
  this.name = name;
  this.say = function() {console.log(this.name)};
}

let cat1 = new Cat('tom'); 
let cat2 = new Cat('bob');
cat1.say === cat2.say // false

但是發(fā)現(xiàn)cat1 cat2的共有方法all并沒有共享吕世,每一個實例對象,都有自己的屬性和方法的副本梯澜。這不僅無法做到數(shù)據(jù)共享寞冯,也是極大的資源浪費(fèi), 那么引入prototype對象:

function Cat(name) {
  this.name = name;
}
Cat.prototype.say = function() {
  console.log(this.name);
}
let cat1 = new Cat('tom'); 
let cat2 = new Cat('bob');
cat1.say === cat2.say 
cat1.say === Cat.prototype.say; // true
cat1.prototype; // undefined
cat1.hasOwnProperty('say');// false

實例對象的constructor屬性指向其構(gòu)造函數(shù)(1)晚伙,這樣看起來實例對象好像“繼承”了prototype對象一樣吮龄。實例沒有prototype,上文最后一行代碼通過hasOwnPropertyk可以判斷say這個方法并不是cat1自己的方法咆疗,如果一個方法沒有在實例對象自身找到漓帚,則向其構(gòu)造函數(shù)prototype中開始尋找(2)

既然實例是繼承自構(gòu)造器的prototype午磁,那么有沒有一個屬性可以直接表示對象的繼承關(guān)系呢尝抖?答案是有的proto,很多瀏覽器都實現(xiàn)了這個屬性迅皇,如下所示昧辽。

cat1.__proto__ === Cat.prototype // true
Cat.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true

從上我們可以發(fā)現(xiàn) Cat 構(gòu)造器的原型為Function.prototype ,Cat.prototype的原型為Object.prototype登颓,所以當(dāng)cat1調(diào)toString時 Cat.prototype上沒有找到 就去Function.prototype上尋找搅荞,這就構(gòu)成了原型鏈。但是對象的原型鏈查找和構(gòu)造函數(shù)的原型查找又有一點小區(qū)別(不查Function),構(gòu)造器生成的實例對象原型鏈的查找過程可以如下表示:

cat1 
 => cat1.__proto__(Cat.prototype) 
 => cat1.__proto__.__proto__(Function.prototype) 
 => cat1.__proto__.__proto__.__proto__ (Object.prototype)

還有通過對象字面量創(chuàng)建的對象的原型鏈查找方式

let obj = {};
obj => obj.__proto__(Object.prototype) ;

這里根據(jù)上文加粗(2)的語言可以得到Function.prototype 的構(gòu)造函數(shù)是Object(3)咕痛。

都有constructor
上文的兩個實例對象cat1 cat2痢甘,他們都具有一個屬性constructor,指向?qū)嵗臉?gòu)建函數(shù)Cat茉贡,意思是他們由Cat創(chuàng)建而來塞栅。實例有一個constructor屬性,指向其構(gòu)造函數(shù)(4)

cat1.constructor === Cat; // true
cat1.constructor === Cat; // true
Cat.constructor === Function; // true
Cat.prototype.constructor === Cat; // true

Object.constructor === Function;// true

構(gòu)造函數(shù)同樣具有construtor腔丧,指向Function放椰,Cat.prototype同樣具有construtor,指向他自身悔据,構(gòu)造函數(shù)的prototype對象的constructor指向該構(gòu)造函數(shù)(5)庄敛。

根據(jù)上文最后一行代碼 可以判斷Object 的構(gòu)造函數(shù) 是Function。則我們可以得到Object是Function的一個實例科汗。如下Object 與 Function的關(guān)系是

??Object是Function的一個實例藻烤。
??Function.prototype 是 Object 的 一個實例。

根據(jù)上文總結(jié)如下:

??實例對象的constructor指向其構(gòu)造器头滔。
??實例對象沒有prototype怖亭。
??實例對象可以通過構(gòu)造函數(shù)的prototype對象實現(xiàn)屬性方法共享±ぜ欤’
??實例對象的proto 原型指向其構(gòu)造函數(shù)的prototype對象
構(gòu)造器的constructor指向 Function兴猩。
構(gòu)造函數(shù)的prototype可以掛在公共屬性方法,prototype的constructor屬性指向該構(gòu)造函數(shù)早歇。
構(gòu)造函數(shù) 的proto 原型指向 Function.prototype倾芝。
構(gòu)造函數(shù)prototype對象的 proto 原型指向Object.prototype。
對象原型指的是對象的 proto 屬性箭跳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晨另,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谱姓,更是在濱河造成了極大的恐慌借尿,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屉来,死亡現(xiàn)場離奇詭異路翻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茄靠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門茂契,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慨绳,你說我怎么就攤上這事账嚎∧玻” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵郭蕉,是天一觀的道長。 經(jīng)常有香客問我喂江,道長召锈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任获询,我火速辦了婚禮涨岁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吉嚣。我一直安慰自己梢薪,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布尝哆。 她就那樣靜靜地躺著秉撇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琐馆。 梳的紋絲不亂的頭發(fā)上恒序,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天歧胁,我揣著相機(jī)與錄音喊巍,去河邊找鬼玄糟。 笑死,一個胖子當(dāng)著我的面吹牛逢并,可吹牛的內(nèi)容都是我干的砍聊。 我是一名探鬼主播贰军,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼帘腹!你這毒婦竟也來了阳欲?” 一聲冷哼從身側(cè)響起球化,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤筒愚,失蹤者是張志新(化名)和其女友劉穎巢掺,沒想到半個月后芍耘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體斋竞,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡浸剩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了重罪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剿配。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡呼胚,死狀恐怖蝇更,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚁廓,我是刑警寧澤纳令,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站漠另,受9級特大地震影響笆搓,放射性物質(zhì)發(fā)生泄漏纬傲。R本人自食惡果不足惜叹括,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一净嘀、第九天 我趴在偏房一處隱蔽的房頂上張望挖藏。 院中可真熱鬧厢漩,春花似錦溜嗜、人聲如沸粱胜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽在塔。三九已至蛔溃,卻和暖如春贺待,著一層夾襖步出監(jiān)牢的瞬間麸塞,已是汗流浹背哪工。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工雁比, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人非洲。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓败京,卻偏偏與公主長得像赡麦,于是被迫代替她去往敵國和親泛粹。 傳聞我的和親對象是個殘疾皇子晶姊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350