[英]JavaScript 'class' and singleton problems
我有一個單例對象使用另一個對象(而不是單例),要求服務器的一些信息:
var singleton = (function(){
/*_private properties*/
var myRequestManager = new RequestManager(params,
//callbacks
function(){
previewRender(response);
},
function(){
previewError();
}
);
/*_public methods*/
return{
/*make a request*/
previewRequest: function(request){
myRequestManager.require(request); //err:myRequestManager.require is not a func
},
previewRender: function(response){
//do something
},
previewError: function(){
//manage error
}
};
}());
這是向服務器發出請求的“類”
function RequestManager(params, success, error){
//create an ajax manager
this.param = params;
this._success = success; //callbacks
this._error = error;
}
RequestManager.prototype = {
require: function(text){
//make an ajax request
},
otherFunc: function(){
//do other things
}
}
問題是我無法從單例對象中調用myRequestManager.require。 Firebug consolle說:“myRequestManager.require不是函數”,但我不明白問題出在哪里。 有沒有更好的解決方案來實現這種情況?
你的代碼按你引用的順序排列,不是嗎? 單例顯示在源中的RequestManager
上方?
如果是這樣,那就是你的問題。 這是相當微妙的(!),但假設您的兩位引用代碼按照您顯示的順序排列,這里是事情發生的順序(我將在下面詳細解釋):
RequestManager
已定義。 RequestManager
實例。 RequestManager
原型被替換為新原型。 由於myRequestManager
實例在原型更改之前已實例化,因此它沒有您在該(新)原型上定義的函數。 它繼續使用實例化時原型對象。
您可以通過重新排序代碼或通過向RequestManager
的原型添加屬性而不是替換它來輕松解決此問題,例如:
RequestManager.prototype.require = function(text){
//make an ajax request
};
RequestManager.prototype.otherFunc = function(){
//do other things
};
這是有效的,因為你沒有替換原型對象,你剛剛添加它。 myRequestManager
看到了添加內容,因為您已將它們添加到它正在使用的對象中(而不是在構造函數的prototype
屬性上設置新對象)。
為什么會發生這種情況有點技術性,我將主要遵循規范。 當解釋器輸入新的“執行上下文”(例如,函數或全局 - 例如,頁面級 - 上下文)時,它執行操作的順序不是嚴格的自上而下的源順序,而是存在階段。 第一階段之一是實例化上下文中定義的所有函數; 在執行任何分步代碼之前發生的事情。 詳見10.4.1(全局代碼),10.4.3(功能代碼)和10.5(聲明綁定)中的所有榮耀,但基本上,這些函數是在第一行逐步代碼之前創建的。 :-)
使用隔離的測試示例最容易看到:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
// Uses Thing1
var User1 = (function() {
var thing1 = new Thing1();
function useIt() {
alert(thing1.foo());
}
return useIt;
})();
// Uses Thing2
var User2 = (function() {
var thing2 = new Thing2();
function useIt() {
alert(thing2.foo());
}
return useIt;
})();
// Thing1 gets its prototype *replaced*
function Thing1() {
this.name = "Thing1";
}
Thing1.prototype = {
foo: function() {
return this.name;
}
};
// Thing2 gets its prototype *augmented*
function Thing2() {
this.name = "Thing2";
}
Thing2.prototype.foo = function() {
return this.name;
};
// Set up to use them
window.onload = function() {
document.getElementById('btnGo').onclick = go;
}
// Test!
function go() {
alert("About to use User1");
try
{
User1();
}
catch (e)
{
alert("Error with User1: " + (e.message ? e.message : String(e)));
}
alert("About to use User2");
try
{
User2();
}
catch (e)
{
alert("Error with User2: " + (e.message ? e.message : String(e)));
}
}
</script>
</head>
<body><div>
<div id='log'></div>
<input type='button' id='btnGo' value='Go'>
</div></body>
</html>
正如您所看到的,如果您運行它, User1
失敗,因為它正在使用的Thing1
實例沒有foo
屬性(因為原型已被替換),但User2
可以工作,因為它使用的Thing2
實例* Thing2
(因為原型是增強的,沒有替換)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.