本文小編為大家詳細介紹“原生Javascript怎么實現繼承”,內容詳細,步驟清晰,細節處理妥當,希望這篇“原生Javascript怎么實現繼承”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
成都創新互聯主營合浦網站建設的網絡公司,主營網站建設方案,重慶APP軟件開發,合浦h5微信小程序搭建,合浦網站營銷推廣歡迎合浦等地區企業咨詢
首先是我們的父類代碼。
在這里我們創建一個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怎么實現繼承”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注創新互聯行業資訊頻道。