2010-09-22 98 views
2

如果我有一個對象,我想從「超級對象」中「繼承」方法以確保一致性。他們將混合變量。 修訂JavaScript繼承

ParentObj = function() 
{ 
    var self = this; 
    this.interval = null 
    this.name = ""; 
    this.timeout = 1000; 

    this.stop = function() 
    { 
     clearInterval(self.interval); 
    }; 

    this.start = function() 
    { 
     self.log("Starting up"); 
     setTimeout(function(){ 
      self.getData(true); 
      self.interval = setInterval(function(){ 
       self.getData(); 
      }, self.timeout) 
     }, 1000); 
    }; 

    this.log = function(msg) 
    { 
     require("sys").log(self.name + ": " + msg); 
    }; 

    this.getData = function(override) 
    { 
     if(override || self.interval) 
     { 
      /** 
      * Allow 
      */ 
      self.log(new Date()); 
     } 
     else 
     { 
      self.log("Unable to override and no interval"); 
     } 
    } 
} 

ChildObj = function() 
{ 
    var self = this; 
    this.name = "Child"; 
    this.timeout = 500; 
    this.start(); 
    setTimeout(function(){ 
     self.stop(); 
    }, 2000); 
} 

ChildObj.prototype = new ParentObj(); 


var c = new ChildObj(); 

這似乎並不正常工作,特別是它沒有看到self.interval,無法將其清除。我打開其他JavaScript繼承方法,如果它們存在,但我真的需要開始封裝到父項的東西。有三個或四個功能是相同的,但有時會更改,這意味着我必須運行十幾個文件才能進行更改,而不是簡單地更改父項。

通過一些建議,我試圖更清楚地定義我要做的功能。理想情況下,所有的「孩子」將有幾個獨特的設置(名稱,間隔,配置設置)和一個getData()方法,而父母管理啓動,停止,記錄和其他任何事情。

回答

0

首先,我不認爲var this.interval是好的。 var關鍵字用於定義一個變量,但在你的情況下,你正在引用一個對象。其次,如果你想聲明「間隔」作爲你的cobj的一種方法,你必須將函數的主體包裝在一個函數中。

所以,這樣一來它的工作對我來說:

var sobj = function() 
{ 
    this.close = function() 
    { 
     clearInterval(this.interval); 
    } 
} 
var cobj = function() 
{ 
    this.initInterval = function(){ this.intervalid = setInterval(function(){ alert("test")}, 5000)}; 
    this.intervalid = null; 
} 
cobj.prototype = new sobj(); 

var inst = new cobj(); 
inst.initInterval(); 

我已經定義了構造函數後,我創建了一個「cobj」對象的實際實例,然後調用「initInterval」初始化「 setInterval的」。

UPD:更新了每個@ MooGoo評論的代碼。

+0

誰給了downvote,請評論 - 我真的很想知道我錯了。 – naivists 2010-09-22 17:51:17

+0

-1不是我的,但這是非常錯誤的。你不需要'var self = this'。在這種情況下,執行'this.interval ='也是一樣的。此外,您正在將函數分配給'interval',而不是間隔ID。正確的代碼是'this.interval = setInterval(/ * func * /,1000);' – MooGoo 2010-09-22 17:52:25

+0

@MooGoo,感謝評論,我不知道OP想要在構造函數中初始化區間。更新我的代碼。 – naivists 2010-09-22 18:03:17

0

使用這種繼承方法,您只能混合變量「上游」。您的子對象將能夠看到其原型的公共屬性,但原型不能查看其子項的屬性。它必須是獨立的。

(編輯:我剛纔注意到您還使用「自我」沒有sobj聲明它。)

sobj = function() 
{ 
    var self = this; 
    self.close = function() 
    { 
     clearInterval(self.interval); 
    } 

    self.interval = null; 
} 
cobj = function() 
{ 
    var self = this; 
    self.interval = setInterval(function(){ /* Do something */}, 1000); 
} 
// set cobj.prototype - see explanation below 

對於如何正確設置原型(和深入瞭解,在繼承將如何工作在JS中),我把你推薦給Douglas Crockford的書JavaScript:好的部分

他實際上在他的網站上發佈了how to properly set the prototype。請確保使用而不是的版本觸摸Object.prototype,因爲如果更改它,許多腳本(用於初學者的jQuery)將會中斷。

+1

不要在super上調用構造函數來獲取一個對象實例作爲子的原型,它會產生令人討厭的副作用並破壞事物。相反,'克隆'超級的原型,並附加到子...看到我的答案。 – 2010-09-22 18:04:12

+0

糟糕,在複製和粘貼時太快了。爲了抓住我的錯誤+1,我會解決它。 – 2010-09-22 18:10:35

+0

我可以使用另一種繼承方法嗎?一個可能不會做這個上游合併? – 2010-09-22 19:17:40

1
  • 通過使對象成爲一次性函數的原型並用'new'調用該函數'克隆'一個對象。

  • 克隆父構造函數的原型,並將結果設置爲子類的原型。

...

/** 
* Extend a constructor with a subtype 
* @param {Function} superCtor  Constructor of supertype 
* @param {Function} subCtor  Constructor of subtype 
* @return {Function}    Constructor of subtype 
*/ 
var extend = (function(){ 

    return function (superCtor, subCtor) { 
    var oldProto=subCtor.prototype; 
    subCtor.prototype=clone(superCtor.prototype); 
    return merge(subCtor.prototype, oldProto).constructor=subCtor; 
    } 

    function Clone(){} 

    /** 
    * Clone an object 
    * @param {Object} obj  Object to clone 
    * @return {Object}   Cloned object 
    */ 
    function clone (obj) { Clone.prototype=obj; return new Clone() } 

    /** 
    * Merge two objects 
    * @param {Object} dst  Destination object 
    * @param {Object} src  Source object 
    * @return {Object}   Destination object 
    */ 
    function merge (dst, src) { 
    for (var p in src) if (src.hasOwnProperty(p)) dst[p]=src[p]; 
    return dst; 
    } 

}());