2014-02-09 37 views
2

我試圖在Javascript中理解原型繼承,但未能應用於以下情況。任何幫助,將不勝感激。Javascript中的原型鏈未更新

我定義構造函數如下:

var base = function() { 
    var priv = "private"; // Private 
    var publ = "public"; // Public through a getter/setter (below) 

    // The object to return 
    var f = {}; 

    f.publ = function (new_val) { 
     if (!arguments.length) { 
      return publ; 
     } 
     publ = new_val; 
     return f; 
    }; 

    return f; 
}; 

有了這個構造,我可以通過調用base();創建對象。這些對象有一個公共方法(publ)。現在

,以下相同的結構,我想有一個創建上述定義由「基地構造」創建的對象繼承對象的新構造:

var myclass = function() { 

    // Other parameters defined here 

    var f = function() { 
     // publ is inherited 
     console.log(f.publ()); 
    }; 

    // Trying to set the prototype of f to the object created by "base()" 
    f.prototype = base(); 

    // Other methods defined here 

    return f; 
}; 

隨着f.prototype = base();我要讓˚F繼承由base()返回的對象中定義的所有方法,但試圖調用f.publ抱怨,因爲 F沒有辦法了公佈

瞭解正在發生的事情將受到歡迎任何幫助

M;

+0

原型繼承要求要麼'新'operator或'Object.create'。你在這裏沒有使用。 – Eric

+0

這看起來不像一個構造函數。你可以使用帶'new'的構造函數。它看起來更像是一個模塊模式。 – elclanrs

+0

正如在一些評論中指出的那樣,使用Object.create來設置繼承的原型部分並在Child中執行Parent.call(this,args)(這將處理從Parent繼承的instace成員)。這裏有更多信息http://stackoverflow.com/a/16063711/1641941 – HMR

回答

2

最常見的方式做原型繼承如下:

function Base() { 
    var priv = "private"; 
    this.publ = "public"; 
} 

現在可以使用new Base創建Base實例。接下來,我們創建MyClass

MyClass.prototype = new Base; 

function MyClass() { 
    alert(this.publ); 
} 

最後,你可以創建如下使用new MyClassMyClass實例:

var a = new MyClass; // alerts "public" 

觀看演示自己:http://jsfiddle.net/b3QyE/


在JavaScript原型繼承可以有點困惑,因爲它的constructor-centric instead of prototype-centric這就是爲什麼我更喜歡使用以下摹效用函數來創建「類」:

function defclass(base, body) { 
    var uber = base.prototype; 
    var prototype = Object.create(uber); 
    var constructor = (body.call(prototype, uber), prototype.constructor); 
    constructor.prototype = prototype; 
    return constructor; 
} 

使用defclass現在你可以調整你的代碼如下:

var Base = defclass(Object, function() { 
    this.constructor = function() { 
     var priv = "private"; 
     this.publ = "public"; 
    }; 
}); 

var MyClass = defclass(Base, function (uber) { 
    this.constructor = function() { 
     uber.constructor.call(this); 
     alert(this.publ); 
    }; 
}); 

它更易於閱讀和理解。一切都封裝在一個單一的功能範圍內,沒有任何東西擺脫位置。此外,您不需要理解使用它的原型繼承。請參閱更新的演示:http://jsfiddle.net/b3QyE/2/

如果您注意到我們從MyClass構造函數調用Base類構造函數。這使您可以使用Base類構造函數初始化實例。您可以通過uber致電Base課程的任何方法。


要了解更多關於原型繼承來看看下面的回答:

  1. JavaScript inheritance and the constructor property
  2. How to achieve pseudo-classical inheritance right on the class declaration?
  3. Benefits of prototypal inheritance over classical?
在JavaScript
+3

注意:建立繼承的一個更好的方法是使用'Object.create(Parent.prototype)'而不是'new Parent'。 http://stackoverflow.com/a/17393153/218196 *編輯:*啊,這就是你在'defclass'函數中做的事情:D –

+0

你引用了Crockford,到目前爲止還沒有能夠生成正確使用他自己稱之爲「僞古典繼承」的文章或演示文稿,也許有人會從JavaScript中獲得更多關於如何使用構造函數和原型的正確文檔,以便他們可以決定如何使用或不使用它。 – HMR

+0

@HMR也許有人會從JavaScript學習Haskell中獲益更多。認真地說,學習Haskell使你成爲一個更好的JavaScript程序員。 –