在個人前兩篇文章中,咱們已經介紹了 js 中實現繼承的兩種模式:原型鏈繼承和借用構造函數繼承。這兩種模式都存在各自的缺點,因此,咱們考慮是否能將這兩者結合到一塊兒,從而發揮兩者之長。即在繼承過程當中,既能夠保證每一個實例都有它本身的屬性,又能作到對一些屬性和方法的複用。這樣就 perfect 了。html
先看咱們以前在借用構造函數繼承中最後用到的代碼:函數
//父類:人 function Person () { this.head = '腦殼瓜子'; this.emotion = ['喜', '怒', '哀', '樂']; //人都有喜怒哀樂 this.eat = function () { console.log('吃吃喝喝'); } this.sleep = function () { console.log('睡覺'); } this.run = function () { console.log('快跑'); } } //子類:學生,繼承了「人」這個類 function Student(studentID) { this.studentID = studentID; Person.call(this); } //Student.prototype = new Person(); var stu1 = new Student(1001); console.log(stu1.emotion); //['喜', '怒', '哀', '樂'] stu1.emotion.push('愁'); console.log(stu1.emotion); //["喜", "怒", "哀", "樂", "愁"] var stu2 = new Student(1002); console.log(stu2.emotion); //["喜", "怒", "哀", "樂"]
在這段代碼中,咱們經過借用構造函數繼承,保證了 stu1 和 stu2 都有各自的父類屬性副本,從而使得各自 emotion 互不影響。但同時帶來的問題是,stu1 和 stu2 都拷貝了 Person 類中的全部屬性和方法,而在 Person 類中,像 eat ( ), sleep ( ), run ( ) 這類方法應該是公用的,而不須要添加到每一個實例上去,增大內存,尤爲是這類方法較多的時候。this
因此咱們想到,是否能把這些方法掛載到父類的原型對象上去,實現方法複用,而後子類經過原型鏈繼承,就能調用這些方法啦?~spa
//父類:人 function Person () { this.head = '腦殼瓜子'; this.emotion = ['喜', '怒', '哀', '樂']; //人都有喜怒哀樂 } //將 Person 類中需共享的方法放到 prototype 中,實現複用 Person.prototype.eat = function () { console.log('吃吃喝喝'); } Person.prototype.sleep = function () { console.log('睡覺'); } Person.prototype.run = function () { console.log('快跑'); } //子類:學生,繼承了「人」這個類 function Student(studentID) { this.studentID = studentID; Person.call(this); } Student.prototype = new Person(); //此時 Student.prototype 中的 constructor 被重寫了,會致使 stu1.constructor === Person Student.prototype.constructor = Student; //將 Student 原型對象的 constructor 指針從新指向 Student 自己 var stu1 = new Student(1001); console.log(stu1.emotion); //['喜', '怒', '哀', '樂'] stu1.emotion.push('愁'); console.log(stu1.emotion); //["喜", "怒", "哀", "樂", "愁"] var stu2 = new Student(1002); console.log(stu2.emotion); //["喜", "怒", "哀", "樂"] stu1.eat(); //吃吃喝喝 stu2.run(); //快跑 console.log(stu1.constructor); //Student
首先,咱們將 Person 類中須要複用的方法提取到 Person.prototype 中,而後設置 Student 的原型對象爲 Person 類的一個實例,這樣 stu1 就能訪問到 Person 原型對象上的屬性和方法了。其次,爲保證 stu1 和 stu2 擁有各自的父類屬性副本,咱們在 Student 構造函數中,仍是使用了 Person.call ( this ) 方法。如此,結合原型鏈繼承和借用構造函數繼承,就完美地解決了以前這兩者各自表現出來的缺點。prototype
若是你以爲文章解決了你的疑惑的話,還請賞我一個推薦哦~ :)設計
做者不才,文中如有錯誤,望請指正,避免誤人子弟。指針
文章內容全都參考於《JAVASCRIPT 高級程序設計》第三版)code