詳解JavaScript中基于原型prototype的繼承特性
JavaScript 中的繼承比較奇葩,無(wú)法實(shí)現(xiàn)接口繼承,只能依靠原型繼承。
原型鏈
原型就是一個(gè)對(duì)象,通過(guò)構(gòu)造函數(shù)創(chuàng)建出來(lái)的實(shí)例會(huì)有指針指向原型得到原型的屬性和方法。這樣,實(shí)例對(duì)象就帶有構(gòu)造函數(shù)的屬性方法和原型的屬性方法,然后將需要繼承的構(gòu)造函數(shù)的原型指向這個(gè)實(shí)例,即可擁有這個(gè)實(shí)例的所有屬性方法實(shí)現(xiàn)繼承。
看下面演示代碼:
//聲明超類(lèi),通過(guò)構(gòu)造函數(shù)和原型添加有關(guān)屬性和方法
function Super(){
this.property = true;
}
Super.prototype.getSuperValue = function() {
return this.property;
};
//聲明子類(lèi)的構(gòu)造函數(shù)
function SubType() {
this.subproperty = false;
}
//將子類(lèi)的原型指向超類(lèi)的實(shí)例,得到超類(lèi)的一切
SubType.prototype = new Super();
SubType.prototype.constructor = SubType;
SubType.prototype.getSubValue = function(){
return this.subproperty;
};
//由子類(lèi)創(chuàng)建對(duì)象,測(cè)試是否繼承超類(lèi)方法和屬性
var instance = new SubType();
console.log(instance.getSuperValue());
所有函數(shù)的默認(rèn)原型都是 Object 的實(shí)例,因此默認(rèn)原型都會(huì)包含一個(gè)內(nèi)部指針,指向 Object.prototype。
使用 instanceof 和 isPrototypeOf 可以確定原型和實(shí)例的關(guān)系:
instance instanceof Object; Object.prototype.isPrototypeOf(instance);
使用原型鏈的時(shí)候,需要謹(jǐn)慎的定義方法。子類(lèi)需要重寫(xiě)超類(lèi)型的某個(gè)方法或者擴(kuò)充,一定要放在替換原型的語(yǔ)句后面,這樣才能生效。此外,通過(guò)原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,這樣會(huì)重寫(xiě)原型鏈:
......
SubType.prototype = new Super();
SubType.prototype = {
....
};
這會(huì)更換指針指向新對(duì)象,從而重寫(xiě)了原型鏈。
原型鏈的繼承方法是有缺陷的,主要有兩個(gè)問(wèn)題:
1,來(lái)自包含引用類(lèi)型值的原型,會(huì)被所有實(shí)例共享。
前面文章介紹過(guò)包含引用類(lèi)型值的原型屬性會(huì)被所有實(shí)例共享,一個(gè)實(shí)例修改,其他實(shí)例會(huì)隨之改變,因此需要在構(gòu)造函數(shù)中定義屬性。而原型鏈繼承的時(shí)候,無(wú)論超類(lèi)中屬性是在構(gòu)造函數(shù)還是原型中定義,全部都變成了實(shí)例對(duì)象被子類(lèi)繼承,從而對(duì)子類(lèi)的實(shí)例產(chǎn)生影響。
2,創(chuàng)建子類(lèi)型的實(shí)例時(shí),不能向超類(lèi)型的構(gòu)造函數(shù)中傳遞參數(shù)。
原型鏈的繼承,直接將子類(lèi)原型指向超類(lèi)的實(shí)例,這時(shí)候可以向超類(lèi)傳遞參數(shù)。但是當(dāng)子類(lèi)創(chuàng)建實(shí)例的時(shí)候,只能向子類(lèi)的構(gòu)造函數(shù)傳遞參數(shù),而不能向超類(lèi)的構(gòu)造函數(shù)傳遞參數(shù)。
因此實(shí)際應(yīng)用中,很少單獨(dú)使用原型鏈。
相關(guān)的一些代碼實(shí)踐
鑒別一個(gè)原型屬性
function hasPrototypeProperty(object, name) {
return name in object && !object.hasOwnProperty(name);
}
在構(gòu)造函數(shù)中使用原型對(duì)象
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName: function () {
console.log(this.name);
},
toString: function() {
}
};
var person1 = new Person('Nicholas');
var person2 = new Person('Greg);
console.log(person1 instanceof Person); // true
console.log(person1.constructor === Person); // true
console.log(person1.constructor === Object); // false
console.log(person2 instanceof Person); // true
console.log(person2.constructor === Person); // true
console.log(person2.constructor === Object); // false
對(duì)象繼承
var person1 = {
name: 'Nicholas',
sayName: function () {
console.log(this.name);
}
};
var person2 = Object.create(person1, {
name: {
configurable: true,
enumerable: true,
value: 'Greg',
writable: true
}
});
person1.sayName(); // Nicholas
person2.sayName(); // Greg
console.log(person1.hasOwnProperty('sayName')); // true
console.log(person1.isPropertyOf(person2)); // true
console.log(person2.hasOwnProperty('sayName')); // false
模塊模式
var person = (function () {
var age = 25;
function getAge() {
return age;
}
function growOlder() {
age++;
}
return {
name: 'Nicholas',
getAge: getAge,
growOlder: growOlder
};
}());
作用域的構(gòu)造函數(shù)
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
var person1 = Person('Nicholas');
console.log(person1 instanceof Person); // false
console.log(typeof person1); // undefined
console.log(name); // Nicholas
相關(guān)文章
JavaScript字符串對(duì)象的concat方法實(shí)例(用于連接兩個(gè)或多個(gè)字符串)
這篇文章主要介紹了JavaScript字符串對(duì)象的concat方法實(shí)例,這個(gè)方法用于連接兩個(gè)或多個(gè)字符串,平時(shí)用+號(hào)比較多,所以這個(gè)方法可能不太常用,需要的朋友可以參考下2014-10-10
簡(jiǎn)述JavaScript中正則表達(dá)式的使用方法
這篇文章主要介紹了JavaScript中正則表達(dá)式的使用方法,正則表達(dá)式是JS進(jìn)階學(xué)習(xí)中的重要知識(shí),本文簡(jiǎn)述了JS對(duì)正則表達(dá)式的支持情況,需要的朋友可以參考下2015-06-06
全面了解JavaScript的數(shù)據(jù)類(lèi)型轉(zhuǎn)換
下面小編就為大家?guī)?lái)一篇全面了解JavaScript的數(shù)據(jù)類(lèi)型轉(zhuǎn)換。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家看,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07
javascript基礎(chǔ)之?dāng)?shù)據(jù)類(lèi)型詳解
這篇文章主要介紹了如何理解JavaScript中的數(shù)據(jù)類(lèi)型,幫助大家更好的學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2021-11-11
深入解讀JavaScript中的Hoisting機(jī)制
這篇文章主要介紹了JavaScript中的Hoisting機(jī)制,涉及到JS中變量聲明的相關(guān)問(wèn)題,需要的朋友可以參考下2015-08-08
探討JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值
這篇文章的主要介紹了JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值,內(nèi)容很充實(shí),需要了解的朋友可以參考下2015-07-07

