javascript4種方法實現繼承

有幾種實現繼承的方式,以下給予總結.

1.打通原型鏈

function Person(name,age){
	this.name=name;
}

Person.prototype.sayName=function(){
	console.log(this.name);
}

function Programmer(job){
	this.job=job;
}

Programmer.prototype=new Person('Tom',23);    //打通原型鏈
Programmer.prototype.constructor=Programmer;   //修改constructor指向

Programmer.prototype.sayJob=function(){
	console.log(this.job);
}
let coder=new Programmer('programmer');
console.log(coder.constructor);
console.log(coder.name);   //Tom
coder.sayName();           //Tom

以上方法有幾個致命的問題
1.)如果子類想擁有自己的name, 我們將會弄不了.
2.)屬性共享 因爲父類的屬性以及方法都掛在了原型鏈上導致當我們修改自己的屬性的時候會污染,尤其是Object,Array等情況.

2.構造繼承

function Person(name,age){
	this.name=name;
}

Person.prototype.sayName=function(){
	console.log(this.name);
}

function Programmer(name,job){
	Person.call(this,name);
	this.job=job;
}

Programmer.prototype.sayJob=function(){
	console.log(this.job);
}

let coder=new Programmer('Tom',23);
//   拿不到,因爲方法不在原型鏈上
coder.sayName();

我們通過把父類鏈的環境指向子類的環境來獲取父類的屬性(相當於es6中的super())。
致命的缺陷,因爲父類的方法是在原型鏈上的,我們使用call來獲取了父類本身的環境,但沒有獲取到父類的原型.

3.組合繼承

於是,我們想到通過組合以上兩種方法來達到我們的目的.

function Person(name,age){
	this.name=name;
}

Person.prototype.sayName=function(){
	console.log(this.name);
}

function Programmer(name,job){
	Person.call(this,name);
	this.job=job;
}

Programmer.prototype=new Person();
Programmer.prototype.constructor=Programmer;

Programmer.prototype.sayJob=function(){
	console.log(this.job);
}

let coder=new Programmer('Tom',23);
console.log(coder);  
console.log(coder.name);  //Tom
coder.sayName();   //Tom

可以看到我們實現了我們想要的繼承方式,但也有幾個缺點.
1.兩處用了構造函數,造成浪費
2.我們只是想要原型鏈上的方法,但屬性也被拿了過來.

最佳實踐方式

function Person(name,age){
	this.name=name;
}

Person.prototype.sayName=function(){
	console.log(this.name);
}

function Programmer(name,job){
	Person.call(this,name);
	this.job=job;
}

Programmer.prototype=Object.create(Person.prototype,{
	constructor:{
		value:Programmer
	}
})

Programmer.prototype.sayJob=function(){
	console.log(this.job);
}

let coder=new Programmer('Tom',23);
console.log(coder);

我們爲了少用一個構造函數,使用了Object.create方法,並且把子類的原型上的constructor指向了父類.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章