2012-12-18 67 views
0

在下面的代碼中,我使用了closure來「保存」這個「this」引用並將它傳遞給一個回調函數。但我想知道,是否有其他技術來完成同樣的事情?是否有其他技術在JavaScript中關閉?

function App() 
{ 
    this.number = 75; 
} 

App.prototype.xmlHandler = function(self) 
{ 
    if (this.number == 99) //true at run-time 
     console.log("this.number == 99 is true"); 
    else 
     console.log("this.number == 99 is false"); 

    if (self.number == app.number) //true at run-time 
     console.log("self.number == app.number is true"); 
    else 
     console.log("self.number == app.number is false"); 
}; 

App.prototype.loadXML = function(url, handler) 
{ 
    var self = this; 
    var req = new XMLHttpRequest(); 
    req.number = 99; 
    req.addEventListener("load", function(){handler.call(req, self);}, false); 
    req.open('GET', url, true); 
    req.send(); 
}; 

App.prototype.init = function() 
{ 
    this.loadXML('resources.xml', this.xmlHandler); 
}; 

var app = new App(); 
app.init(); 

根據xmlHandler方法,主要有兩種不同的「這個」(一個[此]爲REQ對象和應用程序對象的其他[自])。那麼,是否有其他技術可以在同一個屋檐下獲得兩個不同的「這個」值?

+0

不應該'無功自我= this'只是做的把戲,保存當前背景下,精, 你爲什麼會需要這樣做的其他方式? – C5H8NNaO4

+0

您可以將引用另存爲另一個可在該上下文中訪問的對象的屬性,例如,在這種情況下是'event.target'。但是,爲什麼上面的解決方案不好呢? –

+0

我很好奇,如果存在替代技術封閉。或者,關閉唯一可用的東西? – user1906062

回答

1

有,可以創建一個封閉,但沒有冗長的實用功能。

在可以使用ES5 Function.bind方法此特定情況下(墊片容易獲得用於舊的瀏覽器):

App.prototype.loadXML = function(url, handler) { 
    var req = new XMLHttpRequest(); 
    req.number = 99; 
    req.addEventListener("load", handler.bind(this, req), false); 
    req.open('GET', url, true); 
    req.send(); 
}; 

的結果將是handler(其等於this.xmlHandler)將與this被稱爲仍等於其原始值(即App對象),並以req作爲第一個參數。

嚴格地說,這大約是相反的方式,以你目前的xmlHandler定義,但它更符合邏輯恕我直言,有thisApp對象,而不是將其作爲參數傳遞。然後,該功能將被寫入:

App.prototype.xmlHandler = function(req, evt) { 
    if (req.number == ...) { 
     ... 
    } 
    ... 
} 

注意evt參數怎麼也可用 - 在.bind傳遞的參數(S)是前置到由瀏覽器提供的任何參數。

0

一般來說,沒有替代關閉的替代品。

對於this綁定,如果您只需要其中的一個,則可以使用.bind() Function method(本機與ES5.1,很容易shimable)。對於「兩個不同的」這個「值」,你可能需要編寫一個類似的函數來傳遞第二個上下文作爲參數,但是閉包比imho簡單。

0

從實踐角度來說,唯一可以實現這個目標的方法是使用閉包。

也就是說,看你的代碼,我不認爲應該.loadXML()真正關心方面都:

App.prototype.loadXML = function(url, handler) 
{ 
    var req = new XMLHttpRequest(); 
    req.number = 99; 
    req.addEventListener("load", handler, false); 
    req.open('GET', url, true); 
    req.send(); 
}; 

該清理的功能,讓你真正想做的事可以表示在.init()內:

App.prototype.init = function() 
{ 
    var self = this; 

    this.loadXML('resources.xml', function(evt) { 
     // this refers to the XMLHttpRequest 
     // self refers to the current App instance 
     self.xmlHandler(this); 
    }); 
}; 
+0

甚至'this.loadXML(...,this.xmlHandler.bind(this));' – Alnitak

+0

@Alnitak哦,這很漂亮:) –

+0

@Alnitak但問題是,你會失去'XMLHttpRequest'參考進程:) –

0

這可能不是你要找的。無論如何,這是分享'這個'。 對象'內部'不保留其對象,因爲它已成爲'外部'的方法,但它是共享。

讓我知道你是否在尋找比我在這裏寫的更具體的東西。

<html> 
<head> 
</head> 
<body> 
<p id="result1"></p> 
<p id="result2"></p> 
</body> 
<script> 

var outer = function(val, obj){ 

    this['inner'] = obj['inner']; 
      this.val = val; 
    this.inner('result1') 
    this.val2 = 'not 2'; 
    this.inner('result2'); 
}; 
var inner = function(id){ 
    this.val2 = this.val2 || 2; 
    document.getElementById(id).innerHTML = 'this.val='+this.val+'this.val2='+this.val2; 

}; 

new outer('thing', {'inner': inner}); 
</script> 
</html> 
相關問題