一入前端深似海,今後紅塵是路人系列第一彈之淺析JavaScript繼承

繼承算是JavaScript中的一大難點也是必須掌握的知識點。接下來我會列舉一些咱們常見的繼承並給出對應一些的code方便你們理解。javascript

1.類式繼承,既子類原型繼承父類實例化。可是當我利用new關鍵字實例化子類的時候,當我改變子類繼承到父類屬性的時候,會污染到再次實例化的子類它所繼承到的屬性。具體以下css

function SuperClass(){
	this.superValue = true;
	this.languages= ['JS','JAVA'];
}
SuperClass.prototype.getSuperValue = function(){
	return this.superValue;
}
function SubClass(){
	this.subValue = false;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getSubValue = function(){
	return this.subValue;
}
var sub = new SubClass();
console.log(sub.getSuperValue());
console.log(sub.getSubValue());
console.log(sub instanceof SuperClass); //true
console.log(sub instanceof SubClass);	//true
console.log(SubClass instanceof SuperClass); //false
console.log(SubClass.prototype instanceof SuperClass); //true
console.log(sub.languages) //['JS','JAVA']
sub.languages.push('HTML');
var sub1 = new SubClass();
console.log(sub1.languages); //['JS','JAVA','HTML']

2.構造函數繼承,即在子類構造函數中利用call()更改做用域,將子類變量在父類中執行一遍,從而完成繼承。該繼承方式只能繼承父類構造函數中的屬性和方法,並不能直接繼承到父類原型。html

function SuperClass(id,books){
	this.id = id;
	this.books = ['JS','JAVA'];
}
SuperClass.prototype.showBooks = function(){
	return this.books;
}
function SubClass(id,books){
	SuperClass.call(this,id,books)
}
var sub = new SubClass();
sub.books.push('CSS');
console.log(sub.books); //['JS','JAVA','CSS']
var sub1 = new SubClass('superClass');
console.log(sub1.books); //['JS','JAVA']
console.log(sub.showBooks()); //Uncaught TypeError: sub.showBooks is not a function

3.組合繼承,即將類式繼承和構造函數繼承進行功能的結合,造成一個更爲優良的繼承方式。該繼承結合了類式繼承和構造函數繼承,即繼承了父類原型,又繼承了父類構造函數中的屬性和方法。這樣的好處就是在用new關鍵字實例化一個子類的時候改變該子類繼承到的屬性,不會影響下一個實例化的子類繼承到的屬性。可是該繼承方式的缺點就是子類原型繼承父類實例化的時候,也會跑一次父類的構造函數。java

function SuperClass(name){
	this.name = name;
	this.books = ['JS','JAVA'];
}
SuperClass.prototype.getName = function(){
	return this.name;
}
function SubClass(name,time){
	SuperClass.call(this,name);
	this.time = time;
}
SubClass.prototype = new SuperClass('superClass');
SubClass.prototype.getTime = function(){
	return this.time;
}
var sub = new SubClass('superClass');
sub.books.push('CSS');
console.log(sub.books); //['JS','JAVA','CSS']
console.log(sub.getName()); //superClass
var sub1 = new SubClass('superClass');
console.log(sub1.books); //['JS','JAVA']

4.原型式繼承,它是對類式繼承的一個封裝,在原型式繼承中會聲明一個過渡對象,爲的就是建立要返回的新的實例化對象。這裏因爲F過渡類的構造函數沒有內容,因此開銷比較小,使用起來也比較方便。但仍是有着類式繼承同樣的問題。ajax

function inheritObject(o){
	//聲明一個過渡函數
	function F(){}
	//過渡對象的原型繼承父對象
	F.prototype = o;
	return new F();
}
var book = {
	name:'js book',
	alikeBook:['css book','html book']
}
var newBook = inheritObject(book);
newBook.name = 'ajax book';
newBook.alikeBook.push('xml book');
var otherBook = inheritObject(book);
otherBook.name = 'flash book';
otherBook.alikeBook.push('as book');
console.log(newBook.name); //ajax book
console.log(newBook.alikeBook); //['css book','html book','xml book','as book']
console.log(otherBook.name); //flash book
console.log(otherBook.alikeBook); //['css book','html book','xml book','as book']
console.log(book.name); //js book
console.log(book.alikeBook); //['css book','html book','xml book','as book']

5.寄生式繼承,它是對原型繼承的第二次封裝,讓新建立的對象不單單有父類中的屬性和方法並且還能夠添加新的屬性和方法。函數

//聲明基對象
function inheritObject(o){
	//聲明一個過渡函數
	function F(){}
	//過渡對象的原型繼承父對象
	F.prototype = o;
	return new F();
}
var book = {
	name:'js book',
	alikeBook:['css book','html book']
}
function createBook(obj){
	//經過原型繼承方式建立對象
	var o = new inheritObject(obj);
	//拓展新對象
	o.getName = function(){
		console.log(this.name);
	};
	//返回拓展後的新對象
	return o;
}

6.寄生組合式繼承,它將寄生式繼承和構造函數繼承進行結合,造成一個完美的繼承方式。this

/**
 * 寄生式繼承 繼承原型
 * 傳遞參數 subClass 子類
 * 傳遞參數 superClass 父類
 */
function inheritObject(o){
	//聲明一個過渡函數
	function F(){}
	//過渡對象的原型繼承父對象
	F.prototype = o;
	return new F();
}
function inheritPrototype(subClass,superClass){
	//複製一份父類的原型副本保存在變量
	var p = inheritObject(superClass.prototype);
	//修正由於重寫子類原型致使子類的constructor指向父類
	p.constructor = subClass;
	//設置子類的原型
	subClass.prototype = p;
}
//定義父類
function SuperClass(name){
	this.name = name;
	this.colors = ['red','blue'];
}
//定義父類原型方法
SuperClass.prototype.getName = function(){
	return this.name;
}
//定義子類
function SubClass(name,time){
	//構造函數繼承
	SuperClass.call(this,name);
	//子類新增屬性
	this.time = time;
}
//寄生式繼承父類原型
inheritPrototype(SubClass,SuperClass);
//子類新增原型方法
SubClass.prototype.getTime =function(){
	return this.time;
}
var test1 = new SubClass('js book',2014);
var test2 = new SubClass('csc book',2013);
test1.colors.push('black');
console.log(test1.colors); //['red','blue','black']
console.log(test2.colors); //['red','blue']
console.log(test2.getName());
console.log(test2.getTime());

至此,最終完美的寄生組合式繼承便由此誕生了。prototype

此篇文章只是我我的的一些看法,但願能夠幫助到一些對於繼承還比較模糊的小夥伴們。固然,若是有小夥伴覺着哪裏有問題,歡迎指出,你們一塊兒探討交流。code

相關文章
相關標籤/搜索