JavaScript繼承的模擬實現

  咱們都知道,在JavaScript中只能模擬實現OO中的"類",也就意味着,在JavaScript中沒有類的繼承。咱們也只能經過在原對象裏添加或改寫屬性來模擬實現。數組

先定義一個父類,app

1         //父類
2         function ParentClass() {
3             this.className = "ParentClass";
4             this.auth = "Auth";
5             this.version = "V1.0";
6             this.parentClassInfo = function () {
7                 return this.className + "\n" + this.auth + "\n" + this.version;
8             }
9         }

1、prototype 實現: 函數

 1         //子類
 2         //一、prototype繼承
 3         function ChildClassByPrototype() {
 4             this.date = "2013-07-26";
 5             this.classInfo = function () {
 6                 return this.parentClassInfo() + "\n" + this.date;
 7             }
 8         }
 9 
10         ChildClassByPrototype.prototype = new ParentClass();
11 
12         var cctest1 = new ChildClassByPrototype();
13         cctest1.parentClassInfo();
14         cctest1.classInfo();

   這種方式很簡單,只需把父類的實例賦值給子類的prototype屬性就好了,而後子類就可使用父親的方法和屬性了。這裏實際上是用到了原型鏈向上查找的特性,好比這個例子中的 cctest1.parentClassInfo() 方法,JavaScript會先在ChildClassByPrototype的實例中查找是否有parentClassInfo()方法,子類中沒有,因此繼續查找ChildClassByPrototype.prototype屬性,而其prototype屬性的值是ParentClass的一個實例,該實例有parentClassInfo()方法,因而查找結束,調用成功。

2、apply 實現:
this

1         //二、apply繼承
2         function ChildClassByApply() {
3             ParentClass.apply(this, new Array());//ParentClass.apply(this, []);
4             this.date = "2013-07-26";
5             this.classInfo = function () {
6                 return this.parentClassInfo() + "\n" + this.date;
7             }
8         }

 

   JavaScript中的apply能夠理解爲用A方法替換B方法,第一個參數爲B方法的對象自己,第二個參數爲一個數組,該數組內的值爲須要傳遞給A方法對應的參數列表,若是參數爲空,即沒有參數傳遞,可經過 new Array()、[] 來傳遞spa

3、call + prototype 實現: prototype

1         //三、call+prototype繼承
2         function ChildClassByCall() {
3             ParentClass.call(this, arguments);
4             this.date = "2013-07-26";
5             this.classInfo = function () {
6                 return this.parentClassInfo() + "\n" + this.date;
7             }
8         }
9         ChildClassByCall.prototype = new ParentClass();

  callapply做用相似,即都是用A方法替換B方法,只是傳遞的參數不同,call方法的第一個參數爲B方法的對象自己,後續的參數則不用Array包裝,需直接依次進行傳遞。既然做用差很少,爲什麼多了一句 原型賦值呢?這是由於call方法只實現了方法的替換而沒有對對象屬性進行復制操做。
code

  每種方法都有其適用環境,好比,若是父類帶有有參構造函數:對象

1         function ParentClass(className, auth, version) {
2             this.className = className;
3             this.auth = auth;
4             this.version = version;
5             this.parentClassInfo = function () {
6                 return this.className + "\n" + this.auth + "\n" + this.version;
7             }
8         }

這種狀況下,prototype就不適用了,可選用apply或call;blog

 1         function ChildClassByApply(className, auth, version) {
 2             ParentClass.apply(this, [className, auth, version]);
 3             this.date = "2013-07-26";
 4             this.classInfo = function () {
 5                 return this.parentClassInfo() + "\n" + this.date;
 6             }
 7         }
 8 
 9
10         function ChildClassByCall(className, auth, version) {
11             ParentClass.call(this, arguments[0], arguments[1], arguments[2]); //ParentClass.call(this, className, auth, version);
12             this.date = "2013-07-26";
13             this.classInfo = function () {
14                 return this.parentClassInfo() + "\n" + this.date;
15             }
16         }
17         ChildClassByCall.prototype = new ParentClass();

實例化:繼承

1        var cctest2 = new ChildClassByApply("ParentClass", "Auth", "V1.0");
2        var cctest3 = new ChildClassByCall("ParentClass", "Auth", "V1.0");

  在apply和call中,又該如何取捨呢?在OO的繼承中,子類繼承於父類,那麼它應該也是父類的類型。即,ChildClassByCall、ChildClassByApply應該也是ParentClass類型,但咱們用"instanceof"檢測一下就會發現,經過apply繼承的子類,並不是ParentClass類型。因此,咱們建議用call + prototype 來模擬實現繼承。聽說,Google Map API 的繼承就是使用這種方式喲。

參考資料:http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp

相關文章
相關標籤/搜索