2013-06-22 34 views
5

我知道如何使用方法來更改函數/方法調用的上下文:apply,bind,call。我的問題是,有沒有辦法來檢查一個函數/方法是否已經有它的上下文集?JavaScript函數/方法上下文檢查

// given 
var beta; 

function alpha() { 
    return this; 
} 

function isContextSet (fn) { 
    /* check for context binding on fn */ 
} 

beta = alpha.bind("hello"); 

isContextSet(alpha); // returns false 
isContextSet(beta); // returns true 

我想我知道這個問題的答案了,不過想我會問無論如何,如果沒有其他原因比:1,確認我的假設,或2學到一些東西。我敢肯定,我不是第一個問這個問題,但我不知道如何真正找到答案,因爲我得到的答案都是如何使用:.apply(),.call()或。綁定()。

+1

也許這可以幫助:[javascript函數被綁定到什麼物體(什麼是它的「本」)?](http://stackoverflow.com/q/14307264/218196)。 –

+2

_「已經有了它的上下文集合」_「已經」是什麼意思? '.apply()','.call()'和'.bind()'在每次函數被調用時都不會永久設置this [注意'.bind()'返回一個永久的_new_函數具有特定的'this',但實際上並沒有改變_original_函數)。調用一個函數的每種可能的方式都會將'this'設置爲_something_ - 這只是一些隱式的方式,有些是明確的...... – nnnnnn

+0

我添加了一些代碼來展示我正在嘗試着解決的問題。我理解這三種方法是如何工作的,並且我知道如何在調用的主體內檢查函數/方法的上下文。如上所示,如何從調用外部檢查上下文?在JS中我根本無法想到這樣做。 – kalisjoshua

回答

2

實際上,將綁定稱爲「更改」上下文是不正確的。它所做的是將一個功能轉換爲另一個功能,並在特定環境下調用第一個功能。

函數可以通過多種方式綁定。例如,我可以綁定它自己:

function bind(fn,ctxt){ 
    return function(){ 
     fn.apply(ctxt,arguments); 
    }; 
} 

或者,我可以Function.prototype.bind,或做同樣的事情墊片,或下劃線的_.bind綁定。除了上下文之外,我可以將它綁定到初始參數。在每種情況下,如果沒有實際執行該功能,就無法分辨發生了什麼。

綁定只是衆多方法來轉換一個功能到另一個之一。我也可以轉換一個函數從現在開始執行一秒,或者執行兩次。綁定沒有什麼魔力;它只是基於舊的創建一個新的功能。正如另一個答案所建議的那樣,在你可能能夠檢查的函數上沒有設置稱爲[[bound_to]]的特殊變量(除非你使用自己的綁定自定義實現)。沒有事後的辦法來確定如何轉換功能。

我可以想像未來的檢查,對未綁定的版本可能綁定功能,看看它們是否相等最接近的一次。

function log_this(){console.log(this);} 
var bound_func=log_this.bind(my_var); 
console.log(log_this===bound_func); // FALSE 
+1

我想你總結得很好。我同意,我無法真正地測試上下文,正如我在上面定義的那樣。 JavaScript只是提供了太多方法來解決我正在嘗試測試的情況。 – kalisjoshua

0

什麼可以做的是這樣的:

function f(context, whatever) { 
    if(this !== context) { 
     //context has been changed 
    } 
} 

var y = f.bind(thingy); 
y(otherThingy, something); 

你也可以有一個自定義綁定功能,有幾分像這樣的黑客攻擊:

function bind(func, context) {  
    var newFunc = func.bind(context); 
    newFunc._this = context; 
    return newFunc; 
} 

function checkContext(func, context) { 
    return func._this !== context; 
} 
+0

這裏是一個演示我自己版本的自定義綁定函數的小提琴,當我看到您已經用類似的想法覆蓋它時,我將要發佈這個函數作爲答案:http:// jsfiddle .net/jx4fY/ – nnnnnn

-1

我認爲這是爲那些有多愛JavaScirpt有趣的問題,我希望這是響應你在找什麼:


var isContextSet = function (fn) { 
    var testThis = {}; //unique object for testing what is this inside fn 
    return fn.call(testThis) !== testThis; 
} 

我嘗試「設置」 FNfn.call(testThis);,如果該函數返回對新創建的對象的引用(testThis),那麼它不被綁定。我希望你得到它:)

編輯: 這工作時FN retuns這個(如圖問題)。否則,您無法正確定義isContextSet。

+0

如果該函數不'返回這個;'但是其他值或根本沒有值呢?這會產生很多誤報。最簡單的例子:'isContextSet(function(){})'將產生'true',即使函數沒有綁定到特定的值。 –

+0

問題示例函數返回這個。但是,如果它不,那麼你是對的。我從問題引導。 – Zango