參考了文章javascript繼承—prototype屬性介紹(2) 中葉小釵的評論,對這篇文章中的方案二利用一個空函數進行修改,能夠解決建立子類對象時,父類實例化的過程當中特權屬性和特權方法,私有屬性,私有方法的空耗資源問題。javascript
function Person(name,age){ this.name = name; this.age = age; } Person.prototype = { constructor:Person, sayHi:function(){ alert('hi'); } } function Student(name,age,grade){ Person.call(this,name,age); this.grade = grade; } function Empty(){} Empty.prototype = Person.prototype; Student.prototype = new Empty(); Student.prototype.constructor = Student; var p1 = new Person('xiaoming',10); var s1 = new Student('xiaohong',9,3); console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()} console.log(s1);//Student {name="xiaohong", age=9, grade=3, 更多...} console.log(p1.constructor);//Person(name,age) 父類的實例指向還是父類 console.log(s1.constructor);//Student(name,age,grade) //子類的實例指向還是子類
這種狀況下修改Student的prototype就不會影響到Person的prototype對象了,而且,由於直接將Person的prototype賦給Empty的prototype,因此不會存在特權屬性(實例屬性)浪費資源的問題。這樣利用空函數就能很好的解決共有方法的繼承問題了。固然這時Student.prototype中的constructor是Person,因此最好加上Student.prototype.constructor = Student轉換過來。html
2、利用循環遍歷拷貝的方法實現繼承java
一樣對於文章javascript繼承—prototype屬性介紹(2)中的方案三,其實這是一種拷貝的方法,將父類全部的共有方法拷貝到子類中去。函數
function Person(name,age){ this.name = name; this.age = age; } Person.prototype = { constructor:Person, sayHi:function(){ alert('hi'); } } function Student(name,age,grade){ Person.call(this,name,age); this.grade = grade; } for(var i in Person.prototype){Student.prototype[i] = Person.prototype[i]} Student.prototype.constructor = Student; Student.prototype.study = function(){ alert('study'); } var p1 = new Person('xiaoming',10); var s1 = new Student('xiaohong',9,3); console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()} console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...} console.log(p1.constructor);//Person(name,age) 父類的實例指向還是父類 console.log(s1.constructor);//Student(name,age,grade) //子類的實例指向還是子類
這種方法直接將父類的共有方法利用遍歷的模式拷貝到子類中去。這樣就避免了子類實例直接指向父類的問題,也不會出現修改子類的共有方法,對父類產生了影響。也算一種比較完美的繼承。this
固然,這裏主要探討了js裏共有方法的繼承實現問題。對於屬性的繼承主要用的call方法(也能夠當作將父類的構造函數綁定到子類中去)暫時先不探討了。spa