天天看點

原型繼承javascript中的繼承[四] 總結(《Object

PS:今天上午,非常郁悶,有很多簡單基礎的問題搞得我有些迷茫,哎,代碼幾天不寫就忘。目前又不當COO,還是得用心記代碼哦!

    後面兩章中提到的實作繼承的方法,都是《Object-Oriented JavaScript》第六章說起的,書中最後也做了總結:

    In this chapter you learned quite a few ways (patterns) for implementing inheritance.

    The different types can roughly be divided into:

  1. Patterns that work with constructors
  2. Patterns that work with objects

    You can also classify the patterns based on whether they:

  1. Use the prototype
  2. Copy properties
  3. Do both (copy properties of the prototype)

     第六章介紹了一些繼承的方法,分為兩模式:

        基于構造函數生成對象的模式

        直接繼承對象的模式

    也可以按照另一種思路分類:

        應用了原型prototype

        複制屬性

        複制原型的屬性

    可以說,這是實作繼承的最核心的内容,實踐中常常交織在一起。回顧下前文介紹的基本繼承方法:

//構造函數 應用原型鍊
Coder.prototype = new Person("無名");

//構造函數 同享原型鍊
Coder.prototype = Person.prototype;

//構造函數 應用原型鍊 隻繼承原型屬性方法
function extend(Child,Parent){
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
}

//構造函數  應用原型鍊 複制原型屬性
function extend2(Child,Parent){
    var p = Parent.prototype;
    var c = Child.prototype;
    for(var i in p){
        c[i] = p[i];
    }
}

//繼承對象 複制屬性
function extendCopy(p, c){
    var c = c || {};
    for(var i in p){
        c[i]=p[i];
    } 
    return c; 
}

//繼承對象 深複制
function deepCopy(){}

//繼承對象 應用原型鍊
function object(o){
    function F(){};
    F.prototype  = o;
    return new F();
}

//繼承對象 應用原型鍊 複制屬性
function objectPlus(o, stuff){}

//繼承對象 複制屬性
function multi(){}      

    遺留的一些事件

    1.之前的文章中出現以下代碼

function Person(name){
    this.name = name;
}
Person.prototype.sayHello = function(){
    alert(this.name);
};

function Coder(name,language){
   this.language = language;
       this.name = name;
}

Coder.prototype = new Person("無名");
Coder.prototype.constructor = Coder;
Coder.prototype.code = function(){
    alert("i am a "+this.language+" coder");
};      

我們改革下這段代碼,主要處理 子類調用父類的構造函數中初始化代碼,自行對比優缺點:

function Person(name){
    this.name = name;
}
Person.prototype.sayHello = function(){
    alert(this.name);
};

function Coder(name,language){
       Person.apply(this,arguments);
   this.language = language;
}

extend2(Coder,Person);
Coder.prototype.code = function(){
    alert("i am a "+this.language+" coder");
};      

    每日一道理

試試看——不是像企鵝那樣靜靜的站在海邊,翹首企盼機會的來臨,而是如蒼鷹一般不停的翻飛盤旋,執著的尋求。 試試看——不是面對峰回路轉、雜草叢生的前途枉自嗟歎,而是披荊斬棘,舉步探索。 試試看——不是拘泥于命運的禁锢,聽憑命運的擺布,而是奮力敲擊其神秘的門扉,使之洞開一個新的天地。微笑着,去唱生活的歌謠。

通過 Person.apply(this,arguments)調用父類的構造方法,extend2繼承父類的原型方法,最後再擴充原型方法。

    如果擴充的原型方法很多,我想你一定有辦法知道如果通過之前的基礎方法,寫出一個新的符合你自己要求的繼承機制。

    我們完全可以寫一個 extend3(Coder,Person,stuff)的方法~如果你有須要這麼做的話。

    2.幾個函數操作

    obj instanceof F // 判斷對象obj是否是F的執行個體

    F.prototype.isPrototypeOf(obj)//作用同上

    obj.constructor // 傳回obj的構造函數 

    obj.hasOwnProperty('屬性名') // 判斷obj是否有屬于自己的屬性,而不是他所指原型的屬性

    這幾個操作幫助懂得原型鍊、繼承過程,在實踐中也有很重要的作用。

    3.關于 子“類”調用父"類"的方法、屬性

    有三個類 Shape TwoDShape Triangle 形狀、2D形狀、三角形,他們繼承關系。

    對象執行個體須要實作一種方法:toString() 不僅要輸出自己的類名,還要輸出祖輩的類名。

    如何實作呢?

    由于繼承的實作方法挺多的,而且子“類”的這種需求變幻無窮,如何有效控制,文章(本人能力無限)一句話說不清楚,《o-o》中也隻是交叉地說了一下。

    基本的一種思路是 在 Parent加一個靜态屬性uber指向Child.prototype

function extend(Child,Parent){
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;

    Child.uber = Parent.prototype;      
}      
function Shape(){};
Shape.ptototype.name = "shape";
Shape.prototype.toString = function(){
    var result = [];
    if(this.constructor.uber){
        result[result.length] = this.constructor.uber.toString();
    }
    result[result.length] = this.name;
    return result.join(', ');
};

function TwoDShape(){};
extend(TwoDShape,Shape);
TwoDshape.prototype.name = "2dShape";

function Triangle(side, height){
    this.side = side;
    this.height = height;
};
extend(Triangle, TwoDShape);
Triangle.prototype.name = "triangle";
Triangle.prototype.getArea = function(){return this.side*this.height/2;};

var my = new Triangle(3,4);
my.toString();      

複制原型屬性的時候

function extend2(Child,Parent){
    var p = Parent.prototype;
    var c = Child.prototype;
    for(var i in p){
        c[i] = p[i];
    }
    c.uber = p;
}      

    對象直接繼承的時候

function object(o){
    var n;
    function F(){}
    F.prototype = o;
    n = new F();
    n.uber = o;
    return n;

}      

    下面的實作 都是 《o-o》第六章中說起的

    執行個體、原型、構造函數  誰可以最直接地調用方法uber ,以及要發生什麼效果,按需實作。

    uber 是源于德語,super是js中的一個關鍵詞,是以建議應用uber

    到此,《o-o》第六章的内容都介紹完畢,内容基于自己的梳理,增加了自己的懂得,難免有疏漏的地方,請教正。

    歡迎大家看原著,國内也出了翻譯版~

文章結束給大家分享下程式員的一些笑話語錄: 蘋果與谷歌之争就是封閉收費與自由免費思想之争。(别急着把google來膜拜哦?那可是一家公司,以賺錢為目标的公司!當年我Party就是這樣把廣大勞動人民吸引過來的。今天的結果你們都看到了。)

繼續閱讀