JS繼承方式
- 類式繼承(核心思想是將父類的實例對象賦值給子類的原型對象)
- 構造函數(shù)式繼承(核心思想:調用Object.call()方法,將子類的this綁定到父類上)
- 組合式繼承(在子類構造函數(shù)中通過call方法執(zhí)行父類,用以繼承父類的共有屬性,在子類原型上實例化父類用以繼承父類的原型方法)
- 寄生式繼承
1.1 類式繼承
//聲明父類
function SupperClass(){
this.name = '張三'
}
//聲明子類
function SubClass(){}
//將父類的原型賦值給子類的原型對象
SubClass.prototype = new SupperClass()
//實例化子類
var f = new SubClass();
console.log(f.name)
1.2 構造函數(shù)式繼承
//聲明父類
function SupperClass(sex){
this.name = '張三';
this.sex = sex
}
//聲明子類
function SubClass(){
SupperClass.call(this)
}
var person = new SubClass()
console.log(person.name)
1.3 組合式繼承
//聲明父類
function SupperClass(sex){
//父類共有屬性
this.name = '張三';
this.sex = sex
}
//定義父類原型方法
SupperClass.prototype.getName = function(){
return this.name
}
//聲明子類
function SubClass(){
//在子類中執(zhí)行父類
SupperClass.call(this)
}
SubClass.prototype = new SupperClass();
var person = new SubClass();
var person2 = new SubClass();
console.log(person.name) //張三
person.name = '王八'
console.log(person.getName()) //王八
console.log(person2.getName())//張三
1.4 寄生式繼承
//聲明原型繼承函數(shù)
function inhertObj(o){
//聲明一個過渡函數(shù)
function F(){}
//過渡函數(shù)對象的原型繼承自父對象
F.prototype = o;
//返回過渡對象的實例
return new F()
}
/*然而這種方式會子類實例會污染父類的引用型對象
如:*/
var person = {
names:['王八','二狗子'],
sex:'女'
}
var newPerson = inhertObj(person);
newPerson.sex = '男';
newPerson.names.push('漢奸');
var newPerson2 = inhertObj(person);
newPerson2.sex = '不男不女';
newPerson2.names.push('小鬼子');
//父類的值類型的屬性會被復制,引用型會被共享(污染)
console.log(newPerson.sex);//男
console.log(newPerson.names);//["王八", "二狗子", "漢奸", "小鬼子"]
console.log(newPerson2.sex);//"不男不女"
console.log(newPerson2.names);//["王八", "二狗子", "漢奸", "小鬼子"]
<!--由于person.names被污染了,所以繼承了它的子類也沒有得到預期的結果-->
console.log(person.sex);//女
console.log(person.names);//["王八", "二狗子", "漢奸", "小鬼子"]
//寄生式繼承
//聲明基對象
var person = {
names:['王八','二狗子'],
sex:'女'
}
function creatPerson(obj){
//通過原型繼承方式創(chuàng)建新對象
var o = new inhertObj(obj);
//拓展新對象
o.getNames = function(){
console.log(o.names)
}
return o;
}
//寄生組合式繼承
/*
寄生式繼承 繼承原型
傳遞參數(shù) subClass 子類
傳遞參數(shù) superClass 父類
*/
function inhertPrototype(subClass,superClass){
//復制父類的原型用一個變量保存
var p = inhertObj(superClass.prototype);
//將復制對象的constructor重新指向subClass子類
//修正因重寫子類原型導致子類的constructor屬性被更改
p.constructor = subClass;
//再將復制對象(父類對象的副本)賦值給子類的原型
subClass.prototype = p;
}
/*
注意:由于子類原型是父類原型的一個引用對象,所以給子類添加新方法時只能通過點語法一個一個添加,而不能直接修改子類的原型對象否則將會覆蓋從父類原型繼承的對象。
*/
補充:繼承單對象的extend方法
//對象的淺復制
var extend = function(targetObj,sourceObj){
//遍歷源對象中的屬性(不包含引用類型和描述符屬性,如:writable,enumerable)并將它賦值給目標對象
for(var attr in sourceObj){
targetObj[attr] = sourceObj[attr]
}
return targetObj;
}