繼承
JavaScript并不提供原生的繼承機(jī)制泻红,我們自己實(shí)現(xiàn)的方式很多谓着,介紹一種最為通用的
先定義兩個(gè)類
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
};
function Male(age){
this.age = age;
}
Male.prototype.printAge = function(){
console.log(this.age);
};
屬性獲取
對(duì)象屬性的獲取是通過(guò)構(gòu)造函數(shù)的執(zhí)行渡讼,我們?cè)谝粋€(gè)類中執(zhí)行另外一個(gè)類的構(gòu)造函數(shù)绪商,就可以把屬性賦值到自己內(nèi)部苛谷,但是我們需要把環(huán)境改到自己的作用域內(nèi),這就要借助我們講過(guò)的函數(shù)call了
改造一些Male
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
Male.prototype.printAge = function(){
console.log(this.age);
};
實(shí)例化看看結(jié)果
var m = new Male('Byron', 'male', 26);
console.log(m.sex); // "male"
方法獲取
我們知道類的方法都定義在了prototype里面腹殿,所以只要我們把子類的prototype改為父類的prototype的備份就好了
Male.prototype = Object.create(Person.prototype);
這里我們通過(guò)Object.createclone了一個(gè)新的prototype而不是直接把Person.prtotype直接賦值例书,因?yàn)橐藐P(guān)系,這樣會(huì)導(dǎo)致后續(xù)修改子類的prototype也修改了父類的prototype决采,因?yàn)樾薷牡氖且粋€(gè)值
另外Object.create是ES5方法,之前版本通過(guò)遍歷屬性也可以實(shí)現(xiàn)淺拷貝
這樣做需要注意一點(diǎn)就是對(duì)子類添加方法树瞭,必須在修改其prototype之后,如果在之前會(huì)被覆蓋掉
Male.prototype.printAge = function(){
console.log(this.age);
};
Male.prototype = Object.create(Person.prototype);
這樣的話晒喷,printAge方法在賦值后就沒(méi)了,因此得這么寫
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
Male.prototype = Object.create(Person.prototype);
Male.prototype.printAge = function(){
console.log(this.age);
};
這樣寫貌似沒(méi)問(wèn)題了厨埋,但是有個(gè)問(wèn)題就是我們知道prototype對(duì)象有一個(gè)屬性constructor指向其類型捐顷,因?yàn)槲覀儚?fù)制的父元素的prototype雨效,這時(shí)候constructor屬性指向是不對(duì)的,導(dǎo)致我們判斷類型出錯(cuò)
Male.prototype.constructor; //Person
因此我們需要再重新指定一下constructor屬性到自己的類型
最終方案
我們可以通過(guò)一個(gè)函數(shù)實(shí)現(xiàn)剛才說(shuō)的內(nèi)容
function inherit(superType, subType){
var _prototype = Object.create(superType.prototype);
_prototype.constructor = subType;
subType.prototype = _prototype;
}
使用方式
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
};
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
inherit(Person, Male);
// 在繼承函數(shù)之后寫自己的方法徽龟,否則會(huì)被覆蓋
Male.prototype.printAge = function(){
console.log(this.age);
};
var m = new Male('Byron', 'm', 26);
m.printName();
es5之前方法
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
};
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
Male.prototype =Person new;()
Male.prototype.constructor = Male;
// 在繼承函數(shù)之后寫自己的方法,否則會(huì)被覆蓋
Male.prototype.printAge = function(){
console.log(this.age);
};
var m = new Male('Byron', 'm', 26);
m.printName();
es6 類 :extends 關(guān)鍵字
class Animal{
constructor(){
this.body = '肉體'
},
move(){}
}
class Human extends Animal{
constructor(name){
super()
this.name = name
},
useTools(){}
}
var frank = new Human()
這樣我們就在JavaScript中實(shí)現(xiàn)了繼承
hasOwnProperty
hasOwnPerperty是Object.prototype的一個(gè)方法传透,可以判斷一個(gè)對(duì)象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個(gè)處理屬性但是不查找原型鏈的函數(shù)
m.hasOwnProperty('name'); // true
m.hasOwnProperty('printName'); // false
Male.prototype.hasOwnProperty('printAge'); // true
范例 1.實(shí)現(xiàn)面向?qū)ο蟮姆绞綄?shí)現(xiàn) Tab 組件
代碼地址
2.擴(kuò)展 String 的功能增加 reverse 方法朱盐,實(shí)現(xiàn)字符串倒序
String.prototype.reverse = function(){
return this.split("").reverse().join("")
console.log(this)
};
var str = 'hello jirengu'
var str2 = str.reverse();
console.log(str2) // 'ugnerij olleh'