2010-08-24 39 views
16

我有一個JavaScript「類」定義,像這樣:我可以在Javascript中「擴展」一個閉包定義的「類」嗎?

var Welcomer = function(name) { 
    var pName = name; 
    var pMessage = function() { 
    return "Hi, " + pName + "!"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pMessage()); 
    } 
    }; 
}; 

new Welcomer('Sue').sayHi(); 

有沒有一種方式,這樣我可以重新定義公共方法和訪問私有方法和變量的方式,以「繼承」 Welcomer?下面會給我訪問的公共方法,而不是私人的:

var UnhappyWelcomer = function(name) { 
    var pSadMessage = function() { 
    // won't work, b/c I don't have access to pMessage 
    return pMessage() + " Miserable day, innit?"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pSadMessage()); 
    } 
    }; 
}; 
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance 

new UnhappyWelcomer().sayHi(); 
+1

您可能需要閱讀[本文](http://mckoss.com/jscript/object.htm)。 – 2010-08-24 21:35:46

+0

爲該文章添加書籤。 Thx – 2010-08-24 21:39:58

回答

10

對您的問題的簡單回答是。除非你的功能在相同的範圍內,或者你以某種方式「公開」信息(通過返回或設置this),否則你無法做任何事情去獲得對這些定義的事物的訪問。

儘管你可以編輯原始函數,但你可以用這樣的方式重寫事物,使得這些函數可以「傳遞」到擴展函數中,這可以改變對象的「受保護」範圍。下面的代碼應該給出我提議的內容的一個好主意。

var Welcomer = function(name) { 
    var _protected = { 
    name: name, 
    message: function() { 
     return "Hi, " + _protected.name + "!"; 
    } 
    }; 

    return { 
    extendWith: function(extender) { 
     extender.call(this, _protected); 
     return this; 
    }, 
    sayHi: function() { 
     alert(_protected.message()); 
    } 
    }; 
}; 

var UnhappyWelcomer = function(name) { 
    var self = Welcomer(name).extendWith(function(_protected) { 
    _protected.sadMessage = function() { 
     return _protected.message() + " Miserable day, innit?"; 
    }; 
    // extending the public while still having scope to _protected... 
    this.sayHi = function() { 
     alert(_protected.sadMessage()); 
    }; 
    }); 
    return self; 
}; 

UnhappyWelcomer('bob').sayHi(); 
+0

我當然*做*可以訪問原始功能,所以我很樂意以這種方式編寫代碼,使其「保護」而不是「私人」。你能提供一個例子嗎? – 2010-08-24 21:55:37

+0

我想補充一點,這是很浪費「範圍」空間...... – gnarf 2010-08-25 00:18:20

1

如果你真的需要繼承,也有一些圖書館,在那裏,將極大幫助。一種選擇是trait.js,無論如何,它實際上可能成爲JavaScript的標準部分。如果這不會讓你的船漂浮,像jQuery和原型這樣的圖書館就有繼承的助手。

如果你想用最小/從零開始的方法,我強烈建議你使用原型模型的一切。您會看到您的示例中的模式性能大幅提升。

要更直接地解決您的問題,不需要。如果你設計你的'班',那麼你將有一個更容易的時間,所以不依賴私人功能。

+0

我嘗試過'返回jQuery.extend({},Welcomer(),{sayHi:function(){alert(pSadMessage());});',但'extend'顯然只複製對象文本中定義的元素(公共方法),而不是封閉範圍。 – 2010-08-24 21:50:24

+0

是的,你設計你的「類」與在構造函數中定義的私有變量/函數的方式,他們只是變得可見,這就是爲什麼我肯定會移動到更標準的基於原型的結構 – jdc0589 2010-08-24 22:36:45

9

「class」模式不是「class」模式,它被稱爲Module Pattern。它返回的對象與創建它的函數沒有關係,除了它的私有變量的可用性。返回的對象不是創建它的函數的一個實例。

當您調用'new Class()'時,它確實創建了該函數的一個實例,但它也返回了另一個對象。任何進一步的操作實際上都是在返回的對象上,而不是實例。

爲了使用繼承,你真的需要正確地使用原型繼承,我建議你閱讀:

更多閱讀:

遺憾離開你的閱讀材料,但在我看來,你正在探索的可能性。這些文章將對此事給出更深入的瞭解。

一旦你對此事瞭解得更多,你很可能會全然忽略私人成員,並使用_前綴,並像其他人一樣使其成爲公共成員;)這只是簡單和私人成員毫無意義。

相關問題