js 繼承是在前端面試及js庫開發中常常遇到的問題。在面向對象開發時繼承知識也是很是重要,本人閱讀了一些文章總結了js繼承的要點,但願能對你們有所幫助。前端
通俗的說:某一個工程須要藍圖實現來工程,藍圖就是類
。但在一個新工程的藍圖設計時須要複製一些老藍圖上的工程經驗來提高效率,這個過程就至關於繼承。面試
//父類 function SuperClass() { this.superValue = true; } SuperClass.prototype.getSuperValue = function() { return this.superValue; } //子類 function SubClass() { this.subValue = false; } SubClass.prototype = new SuperClass(); SubClass.prototype.getSubValue = function() { return this.subValue; } var instance = new SubClass(); console.log(instance instanceof SuperClass)//true console.log(instance instanceof SubClass)//true console.log(SubClass instanceof SuperClass)//false
這種方式是最原始的方式,使用父類的一個實例重寫到子類原型對象上,從而實現父類成員的繼承,有點繼承的樣子,可是總以爲怪怪的,你肯定把一個實例賦值到原型上真的沒有問題嗎?數組
缺點:瀏覽器
SubClass.prototype = new SuperClass();
重寫語句以後,很不方便function SuperClass(id) { this.books = ['a','b']; this.id = id; } SuperClass.prototype.showBooks = function() { console.log(this.books); } function SubClass(id) { //繼承父類 SuperClass.call(this,id); } var instance1 = new SubClass(10); var instance2 = new SubClass(11); instance1.books.push('c'); console.log(instance1) console.log(instance2) instance1.showBooks();
比上面一個稍微好了一點,也能傳參了,每次出來的數組也是惟一的了。原理是在子類構造的時候使用call的特性借用一下父類的構造函數,把父類的成員都設置在子類中來實現繼承。額。。那原型呢?
缺點:函數
function SuperClass(name) { this.name = name; this.books = ['A','B']; } SuperClass.prototype.getBooks = function() { console.log(this.books); } function SubClass(name,time) { SuperClass.call(this,name); this.time = time; } SubClass.prototype = new SuperClass(); SubClass.prototype.getTime = function() { console.log(this.time); }
還能夠,能用,原理也就是結合了以上兩種(構造函數、類式繼承)的繼承方式,並修復了嚴重的缺點。之前應該用這種方法的人也比較多吧
缺點:this
function inheritObject(o) { //聲明一個過渡對象 function F() { } //過渡對象的原型繼承父對象 F.prototype = o; //返回過渡對象的實例,該對象的原型繼承了父對象 return new F(); } var book = { name:'A book', likeBook:['B Book','C book'] } var newBook = inheritObject(book); newBook.name = 'AA1 book'; newBook.likeBook.push('CC book'); var otherBook = inheritObject(book); otherBook.name = 'EE book'; otherBook.likeBook.push('FF book'); console.log(newBook,otherBook);
這就像類式繼承同樣,直接把父的成員放到子類的原型上,經過原型鏈來實現繼承。inheritObject就像是object.create()和new的模擬實現,產出很是純淨的對象。
黑人問號.jpg。使用這種方法意思是放棄了構造函數來實現繼承?
缺點:prototype
var book = { name:'A book', likeBook:['B book','C book'] } function createBook(obj) { //經過原型方式建立新的對象 var o = new inheritObject(obj); // 拓展新對象 o.getName = function(name) { console.log(name) } // 返回拓展後的新對象 return o; }
依然保留了inheritObject函數來實現父成員的繼承,相比上面的原型繼承代碼更有組織性了,單獨封裝了一個函數來實現繼承,而後使用原型繼承來繼承對應的父類
缺點:
已經差很少作到了繼承,可是原型繼承問題依然沒有解決設計
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.books=['a book','b book']; } SuperClass.prototype.getName = function() { console.log(this.name); } function SubClass(name,time) { SuperClass.call(this,name); this.time = time; } inheritPrototype(SubClass,SuperClass); SubClass.prototype.getTime = function() { console.log(this.time); } var instance1 = new SubClass('f1','2017') var instance2 = new SubClass('r2','2018'); instance1.books.push('new book'); console.log(instance1,instance2);
繼承終極版。這個繼承方式是在解決組合繼承遇到的問題,先給子類鏈接上純淨的父原型成員,而後再借用父類構造函數獲取到父構造函數裏的成員,基本解決上面出現的問題。code
剩下沒說的就是ES6的繼承,也是至關於一個ES6的語法糖,源碼也是基於寄生組合式繼承。缺點就是對低版本的瀏覽器不友好, 以上總結了6種js繼承方式,每個繼承方式都是修復以前繼承的不足,重點是理解它們的特色和之間的差別,弄明白爲何要這樣作,這樣才能完全理解js繼承的內容。最後,但願能對你有幫助~對象