您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關原生Javascript如何實現繼承,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
最近在復習javascript的一些基礎知識,為開啟新的征程做準備。所以開始記錄一些自己學習的內容。
廢話少說,上代碼!
首先是我們的父類代碼。
在這里我們創建一個Person的類作為父類,它的構造函數需要2個參數name和age。
然后我們在它的原型上添加一個sayHi的方法。
//父類 function Person (name, age) { this.name = name || 'no name'; this.age = age || 0; } Person.prototype.sayHi = function () { console.log('Hi, I\'m ' + this.name + ' and i\'m ' + this.age + ' years old!'); } var p = new Person('A',20); p.sayHi();//Hi, I'm A and i'm 20 years old!
//原型繼承 function Teacher(){ } Teacher.prototype=new Person('B',22); Teacher.prototype.constructor=Teacher; var t = new Teacher(); t.sayHi();//Hi, I'm B and i'm 22 years old! console.log(t instanceof Person);//true console.log(t instanceof Teacher);//true
從上面的代碼來看,Teacher 的實例擁有了 Person 的屬性和方法。并且實例對象既是 Person的實例也是 Teacher的實例。而且這種繼承方式特別的簡單。
我們可以很容易的就發現Teacher類的 name和 age是固定的,都是name=B和age=22,換句話說就是我們無法實現按照我們的意愿給父類的構造函數傳參。并且一個我們不能給一個 Teacher 指定多個原型,也就是沒法 多繼承。然后我們看下下面這段代碼:
var t1 = new Teacher(); var t2 = new Teacher(); Teacher.prototype.name = "C"; t1.sayHi();//Hi, I'm C and i'm 22 years old! t2.sayHi();//Hi, I'm C and i'm 22 years old!
上面這段代碼中我們可以看到當原型中的屬性或者方法被改變時,所有的子類實例的屬性和方法也會跟著被改變,也就是原型繼承的另一個缺點:所有子類共享同一個原型對象
這里說到了原型,我很早之前也寫過一個關于原型的隨筆,不過可能也是有些模糊,現在的理解和當時有所不同,我會在后面重新寫一篇關于原型的隨筆。(寫好了我會附上連接)
//構造函數繼承 function Teacher (name, age) { Person.call(this, name, age); } var t1 = new Teacher('B', 22); var t2 = new Teacher('C', 30); console.log(t1.name);//B console.log(t2.name);//C console.log(t1 instanceof Person);//false console.log(t1 instanceof Teacher);//true t1.sayHi();//TypeError: t1.sayHi is not a function t2.sayHi();//TypeError: t1.sayHi is not a function
相對于 原型繼承 , 構造函數繼承解決了所有的子類實例共享統一原型的問題,也可以給父類的構造函數傳參,并且我們可以在子類的構造函數中調用多個父類的構造函數,實現所謂的多繼承(這里的多繼承是指子類通過call,apply等方法去調用父類的構造函數使其擁有父類的屬性和方法,但是js中一個函數對象只存在一個 prototype,所以其實我們沒法通過原型鏈的形式去體現出多繼承)
上面的代碼中我們可以看出創建的實例只是 子類的實例 并不是 父類的實例 ,不能直觀的體現出繼承,這種繼承方式也無法繼承父類的原型上的屬性和方法。
//組合式繼承 function Teacher (name, age) { Person.call(this, name, age); } Teacher.prototype = new Person(); Teacher.prototype.constructor = Teacher; var t1 = new Teacher('B', 22); var t2 = new Teacher('C', 30); Teacher.prototype.name = "D"; console.log(t1.name);//B console.log(t2.name);//C t1.sayHi();//Hi, I'm B and i'm 22 years old! t2.sayHi();//Hi, I'm C and i'm 30 years old! console.log(t1 instanceof Person);//true console.log(t1 instanceof Teacher);//true
組合式繼承就是結合了原型繼承和構造函數繼承的優點,解決了兩種方式存在的一些缺點。但是我們會發現每當我們去創建一個子類實例的時候都會去創建一個父類的實例,盡管父類實例不是同一個實例(內存地址不一樣),但是他們其實屬性和方法上完全一致,所以我們通過下面這種(寄生式組合繼承)方式完善它,以避免不必要的實例構造。
//寄生式組合繼承 function Teacher (name, age) { Person.call(this, name, age); } Teacher.prototype = Object.create(Person.prototype); Teacher.prototype.constructor = Teacher; var t1 = new Teacher('B', 22); var t2 = new Teacher('C', 30); Teacher.prototype.name = "D"; console.log(t1.name);//B console.log(t2.name);//C t1.sayHi();//Hi, I'm B and i'm 22 years old! t2.sayHi();//Hi, I'm C and i'm 30 years old! console.log(t1 instanceof Person);//true console.log(t1 instanceof Teacher);//true
上面的方式解決了我們沒創建一個子類實例都去創建一個父類實例的問題,這也是最為常用的一種js的繼承方式,如果我們通過Babel去把ES6中的class的繼承轉成ES5的代碼,我們會發現就是用的寄生式組合繼承。
關于“原生Javascript如何實現繼承”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。