標籤:call 注意 tor argument nts style apply 世界 people
眾所周知,物件導向編程有三個重要的概念: 封裝、繼承、多態。而JS作為物件導向的弱類型語言,應該說是基於對象的語言,正如常說的,JS的世界裡,萬物皆對象。雖然JS本身不是物件導向的語言,我們可以通過類比的方法,來實作類別似JAVA式的類繼承。
1、建立一個自訂對象
//建構函式function People(name,age){ this.name = name; this.age = age;}//定義原型對象People.peototype={ getName : function(){ return this.name; }, getAge : function(){ return this.age; }}
var p1 = new People(‘leaf‘,10);
console.log(p1.getName()) //leaf
2、當執行 var p1 = new People(‘leaf‘,10);內部主要做了這幾件事
1. 建立新的Null 物件(new Object());
2. 設定新對象的__proto__繼承建構函式的prototype (p1.__proto__===People.prototype );
3. 將這個對象通過this關鍵字傳遞到建構函式中並執行建構函式。
4. 將這個對象賦值給p1.
3、簡單的繼承,看看
建立student類,它從People繼承了原型prototype中所有的屬性。
function Student(name, age, score) { this.name = name; this.age = age; this.score = score;}// 將Studen原型指向Person的一個執行個體(其實就是Student.prototype裡的__proto__指向了People的執行個體中的__proto__,
而People的執行個體中的__proto__又指向了People.prototype)。因為People的執行個體可以調用People原型中的方法, 所以Studen的執行個體也可以調用Person原型中的所有屬性。
Studen.prototype = new Person();
Student.prototype.constructor = Student; //避免執行個體的constructor屬性指向Object函數
Studen.prototype.getScore= function() { return this.score; }; var p1 = new Employee("leaf", "12", "100"); console.log(p1.getName()); // "leaf
4、3中的方法存在的問題
1、在建立Student建構函式和原型時,就對Pelple進行了執行個體化,這是不合適的。
2、Student的建構函式沒法調用父類Person的建構函式,導致在People建構函式中對name和age屬性的重複賦值。
3、Student中的函數會覆蓋Pelple中的同名函數,沒有重載的機制.
5、修複之後更加優雅地繼承
//建構函式function People(name,age){ this.name = name; this.age = age;}//定義原型對象People.prototype={ constructor : People, getName : function(){ return this.name; }, getAge : function(){ return this.age; }}//定義一個Student類function Student(name,age,score){ //調用Peopel建構函式,this指向了People People.apply(this,arguments); this.score=score;}Student.prototype = { constructor :Student, getScore:function(){ return this.score; }}//讓Student的原型對象繼承People的原型對象
Object.setPrototypeOf( Student.prototype, People.prototype);
var p2 = new Student(‘kafu‘,10,99);
console.log(p2.getScore());//99
console.log(p2.getName()); //kafu
console.log(Student.prototype.constructor==Student); //true、
6、總結
主要利用兩點
1、在子類型建構函式中調用父類型建構函式,改變this的指向。
注意:可以使用call(this,參數屬性)、apply(this,[參數數組])
2、利用Object.setPrototypeOf()
注意:該方法的Polyfill
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) { obj.__proto__ = proto; return obj; }
優雅地實現JavaScript的繼承