2013-06-22 9 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関数が(この "this"とは何ですか?)](http://stackoverflow.com/q/14307264/218196)。 –

+2

_ "は既にコンテキスト設定を持っています" _ "既に"という意味ですか?関数が呼び出されるたびに '.apply()'、 '.call()'および '.bind()'は 'this'を永久に設定しません(' .bind() 'は_new_特定の 'this 'を持っていますが、_original_関数を実際には変更しません)。すべての可能な方法で関数を呼び出す方法は 'this'を_something_に設定します - 暗黙的に行う方法と明示的に行う方法です... – nnnnnn

+0

私は何を得ようとしているのかを示すコードをいくつか追加しました。私は3つのメソッドがどのように動作するのか理解しており、呼び出しの本体の中で関数/メソッドのコンテキストをチェックする方法を知っています。上記のように、呼び出しの外からコンテキストをチェックするにはどうすればよいですか?私はJSでそれをする方法を考えることはできません。 – kalisjoshua

答えて

2

実際には、バインディングをコンテキストの「変更」と呼ぶのは間違いです。それは、ある関数を、特定のコンテキストで最初の関数を呼び出す関数に変換します。

関数は多くの方法でバインドできます。例えば、私はそれを自分自身をバインドすることができます:

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

かを、私はFunction.prototype.bind、または同じことを行い、シム、またはアンダースコアの_.bindとそれを結合することができます。私は文脈に加えてそれを最初の議論に結びつけることができました。いずれの場合も、本質的に実際に関数を実行することなく何が起こったのかを知る方法はありません。

バインディングは、ある関数を別の関数に変換する多くの方法の1つに過ぎません。私は今から1秒後に実行する関数を変換することも、2回実行することもできます。縛りに関しては何も魔法はありません。古いものに基づいて新しい関数を作成するだけです。あなたが調べることができるかもしれない関数に[[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; 
} 

私は FN この「を設定」してみてください:fn.call(testThis);、その関数が新しく作成されたオブジェクト(testThis)への参照を返した場合、バインドされません。私はあなたがそれを得る願っています:)

EDIT: これは FN retuns(質問のように)これを動作します。それ以外の場合は、isContextSetを適切に定義することはできません。

+0

関数が ';これを返すのではなく、'他の値か全く値がない場合はどうなりますか?これは多くの偽陽性を引き起こすでしょう。最も簡単な例:関数が特定の値に束縛されていなくても、 'isContextSet(function(){})'は 'true'を返します。 –

+0

質問の例の関数はこれを返します。しかし、そうでなければ、あなたは正しいです。私は質問から導かれました。 – Zango

関連する問題