原型和繼承

原型部分

簡單創(chuàng)建一個(gè)構(gòu)造函數(shù)與實(shí)例:

function Person() {

}
Person.prototype.name = 'Zhar';
Person.prototype.age = 30;
Person.prototype.say = function(){
  console.log(this.name);
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Zhar
console.log(person2.name) // Zhar

Person 為構(gòu)造函數(shù)
person是Person 的一個(gè)實(shí)例對(duì)象

1、instanceof

instanceof 用于判斷一個(gè)對(duì)象是否是另一個(gè)對(duì)象的實(shí)例(該方法在原型鏈中依然有效)

注:instance 為例子芬膝,實(shí)例的意思

console.log(person1 instanceof Person);//true
console.log(person2 instanceof Person);//true
var arr = new Array();
console.log(arr instanceof Array);//true

2初斑、prototype

每個(gè)函數(shù)都有一個(gè)prototype屬性(只有函數(shù)才有)
  函數(shù)的 prototype屬性指向了該構(gòu)造函數(shù)創(chuàng)建的實(shí)例的原型(是實(shí)例的原型乍惊,而不是函數(shù)的原型)蔫耽。

3、constructor

默認(rèn)情況下外永,所以原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造器)屬性崎脉,這個(gè)屬性指向構(gòu)造函數(shù)。

原型是什么伯顶?
每一個(gè)對(duì)象都有一個(gè)與之關(guān)聯(lián)的'原型’對(duì)象囚灼,每一個(gè)對(duì)象都會(huì)從原型繼承屬性

如何訪問對(duì)象的原型骆膝?
在ECMA中,并沒有規(guī)定直接訪問對(duì)象原型的方法灶体,但 Firefox/Chrome/safari 在每一個(gè)對(duì)象上都有一個(gè)proto屬性來訪問原型對(duì)象阅签。

4、_proto__

console.log(Person.prototype);
console.log(person);
console.log(person.__proto__);

__proto__存在于實(shí)例與構(gòu)造函數(shù)的原型對(duì)象之間赃春,而不是存在于實(shí)例與構(gòu)造函數(shù)之間

  • 小結(jié)
  • 構(gòu)造函數(shù)的prototype屬性和實(shí)例的proto指向構(gòu)造函數(shù)的原型
  • 構(gòu)造函數(shù)原型的constructor(構(gòu)造器)指向該構(gòu)造函數(shù)
原型.PNG

5愉择、isPrototypeOf

可通過object1.isPrototypeOf(object2)來判斷一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈中,即 object1 是否存在于 object2的原型鏈中织中。換句話講:判斷 object2是否有一個(gè)指針指向 object1锥涕。

Person.prototype.isPrototypeOf(person1);//true
Person.prototype.isPrototypeOf(person2);//true

6、getPrototypeOf(ES5)

返回一個(gè)對(duì)象的原型

一些判斷:

person.__proto__ === Person.prototype;//true
person.__proto__.constructor === Person.prototype.constructor;//true
person1.__proto__ === person2.__proto__;//true
person1.say === person2.say;//true
Object.getPrototypeOf(person1) === Object.getPrototypeOf(person2);//true
Object.getPrototypeOf(person1) === Person.prototype;//true

7狭吼、hasOwnProperty

通過hasOwnProperty(propertyName)來檢測一個(gè)屬性是存在于實(shí)例還是原型中

console.log(person1.hasOwnProperty("name"));//false;
person1.name = "newName";
console.log(person1.hasOwnProperty("name"));//true

8层坠、in

通過in關(guān)鍵字可以判斷某個(gè)對(duì)象是否包含某個(gè)屬性,而不管這個(gè)屬性是屬于實(shí)例還是原型

console.log("name" in person1);//true;
person1.name = "newName";
console.log("name" in person1);//true

通過 hasOwnProperty() 與 in 相結(jié)合刁笙,可精確定位一個(gè)屬性是屬于原型還是實(shí)例

8破花、keys(obj) ES5

keys(object)方法可返回對(duì)象所有可枚舉屬性的字符串?dāng)?shù)組

console.log(Object.keys(person1));//[]
person1.name = "newName";
console.log(Object.keys(person1));//["name"]
console.log(Object.keys(Person.prototype));//[ 'name', 'age', 'say' ]

keys()返回的是該對(duì)象的屬性數(shù)組,并不包含其構(gòu)造函數(shù)上的屬性

繼承部分

1疲吸、原型鏈?zhǔn)嚼^承

讓一個(gè)函數(shù)的原型對(duì)象(funtion.prototype)指向另一個(gè)原型的指針(實(shí)例.__ proto__)座每,而另一個(gè)原型中也包含指向另外一個(gè)構(gòu)造函數(shù)的指針,依此層層嵌套摘悴,形成原型鏈

function Animal() {
    this.topType = "脊椎動(dòng)物";
}
Animal.prototype.getTopType = function(){
    return this.topType;
}
function Person() {
    this.secondType = "人類";
}

Person.prototype = new Animal();
Person.prototype.getSecondType = function(){
    return this.secondType;
}
var person = new Person();
console.log(person.topType+"--"+person.secondType);//脊椎動(dòng)物--人類

在上面的例子中峭梳,Person.prototype=new Animal() 即是將 Animal 實(shí)例賦給了 Person.prototype

結(jié)合前面原型中的講解,new Animal 產(chǎn)生一個(gè) Animal 實(shí)例蹂喻,該實(shí)例對(duì)象有一個(gè)_proto_指向其構(gòu)造函數(shù)的prototype葱椭,將該實(shí)例賦值給 Person 的原型,意味著Person的原型 既擁有了 Animal 的所有實(shí)例屬性或方法口四,還包含了一個(gè)指向 Animal的原型的指針孵运。

缺點(diǎn)

1.引用數(shù)據(jù)類型問題

在JS面向?qū)ο笠还?jié)中,我們?cè)?jīng)嘗試將引用數(shù)據(jù)類型賦值給原型的屬性(參見創(chuàng)建對(duì)象一節(jié)的原型模式)蔓彩,結(jié)果出現(xiàn)實(shí)例間相互影響治笨,在原型繼承時(shí),也會(huì)出現(xiàn)此問題赤嚼,觀察下例:

function Person(){
  this.desc = ["北京"];
}
function Student(){}
Student.prototype = new Person();
var s1 = new Student();
var s2 = new Student();
s1.desc.push("昌平");
console.log(s1.desc);//[ '北京', '昌平' ]
console.log(s2.desc);//[ '北京', '昌平' ]

Person 函數(shù)含有一個(gè)desc 屬性旷赖,則 Person的實(shí)例會(huì)包含各自的一個(gè) desc 屬性。但此時(shí)的 Student 通過原型鏈繼承了 Person探膊,Student 的 prototype 則變成了 Person 的一個(gè)實(shí)例杠愧,則 Student 就擁有了一個(gè) desc 屬性,相當(dāng)于使用 Student.prototype.desc=[…]為 Student 添加了這樣一個(gè)原型屬性逞壁,結(jié)果顯而易見流济。

2.傳參問題

通過前面的代碼锐锣,會(huì)發(fā)現(xiàn),在使用原型鏈繼承時(shí)绳瘟,無法向父級(jí)構(gòu)造函數(shù)傳遞參數(shù)

2雕憔、借用構(gòu)造函數(shù)式繼承

通過使用 call 或 apply 來實(shí)現(xiàn)借用式繼承

call 或 apply :更改函數(shù)執(zhí)行的上下文環(huán)境

function Person(name){
  this.name = name;
}
function Student(name){
  Person.call(this,name);
}
var student = new Student("zhar");
console.log(student.name);//zhar

上面的代碼中,使用了 call糖声,在 Student 的實(shí)例環(huán)境中調(diào)用了 Person 構(gòu)造函數(shù)斤彼,更改了 Person 的 this 指向?yàn)楫?dāng)前實(shí)例環(huán)境,最終 Student的實(shí)例就擁有了 name 屬性

優(yōu)勢

可以在調(diào)用構(gòu)造函數(shù)時(shí)蘸泻,向'父級(jí)'傳遞參數(shù)琉苇,如上例中一樣,在調(diào)用 Person 時(shí)傳入了 name 值

劣勢

無法繼承原型屬性或方法

function Person(name){
  this.name = name;
}
Person.prototype.say = function(){
  console.log(this.name);
}
function Student(name){
  Person.call(this,name);
}
var student = new Student("zhar");
console.log(student.name);//zhar
student.say();//報(bào)錯(cuò)  student.say is not a function

3悦施、組合繼承

將原型鏈?zhǔn)嚼^承與借用構(gòu)造函數(shù)式繼承組合在一起并扇,結(jié)合二者的優(yōu)勢。通過原型鏈實(shí)現(xiàn)對(duì)原型屬性或方法的繼承抡诞,通過借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承穷蛹。

function Person(name){
  this.name = name;
}
Person.prototype.say = function(){
  console.log(this.name);
}
function Student(name){
  Person.call(this,name);
}
Student.prototype = new Person();
var student = new Student("zhar");
console.log(student.name);//zhar
student.say();//zhar
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昼汗,隨后出現(xiàn)的幾起案子肴熏,更是在濱河造成了極大的恐慌,老刑警劉巖顷窒,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛙吏,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹋肮,警方通過查閱死者的電腦和手機(jī)出刷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門璧疗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坯辩,“玉大人,你說我怎么就攤上這事崩侠∑崮В” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵却音,是天一觀的道長改抡。 經(jīng)常有香客問我,道長系瓢,這世上最難降的妖魔是什么阿纤? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮夷陋,結(jié)果婚禮上欠拾,老公的妹妹穿的比我還像新娘胰锌。我一直安慰自己,他們只是感情好藐窄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布资昧。 她就那樣靜靜地躺著,像睡著了一般荆忍。 火紅的嫁衣襯著肌膚如雪格带。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天刹枉,我揣著相機(jī)與錄音叽唱,去河邊找鬼。 笑死微宝,一個(gè)胖子當(dāng)著我的面吹牛尔觉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芥吟,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼侦铜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钟鸵?” 一聲冷哼從身側(cè)響起钉稍,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棺耍,沒想到半個(gè)月后贡未,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒙袍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年俊卤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片害幅。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡消恍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出以现,到底是詐尸還是另有隱情狠怨,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布邑遏,位于F島的核電站佣赖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏记盒。R本人自食惡果不足惜憎蛤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纪吮。 院中可真熱鬧俩檬,春花似錦栏豺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晚胡,卻和暖如春灵奖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背估盘。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工瓷患, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人遣妥。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓擅编,卻偏偏與公主長得像,于是被迫代替她去往敵國和親箫踩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爱态,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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