2011-09-18 14 views
15

JavaScript Gardenを介してブラウズしていましたが、「高速なアンバインドラッパー」を作成するために使用されるFunction.call.applyハックを見つけました。それは言う:JavaScriptでFunction.call.applyを使用する目的は何ですか?

もう一つのトリックは、呼び出しと適用の両方を使用して高速のバインドされていないラッパーを作成することです。 Function.applyで十分だろうというときFunction.call.applyを使用して、なぜわざわざ

function Foo() {} 

Foo.prototype.method = function(a, b, c) { 
    console.log(this, a, b, c); 
}; 

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN 
Foo.method = function() { 

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN) 
    Function.call.apply(Foo.prototype.method, arguments); 
}; 

は、私が理解していないことです。結局のところ、両方とも意味的に同等です。

+0

私は[JavaScript Garden](http://javascriptgarden.info/)へのリンクを投稿しました。投稿を含むセクションに直接ジャンプしたい場合は、[ここ](http://javascriptgarden.info/#function.arguments)をクリックしてください。 –

+0

tnx - これは、このハックがいくつかのスピードを上げることを暗示しているようですが、本当に、ちょうど**それを使用しないでください**。 – c69

+2

@Aadit 'Function.call.apply'と' Function。'関数'コンストラクタを適用しようとしている間、前者は 'Function.call'を適用するので、ここでは同じであることはできません。私の答えの詳細は、Ivo Wetzelがこれに答えるために来たのであれば、はるかに雄弁で分かりやすいだろう。これはかなり深いものです。私は同僚が費やすことを望んでいない限り、おそらくあなたが使うべきものではないことに同意します。分かりません。 :) –

答えて

13

いいえ、Function.call.applyFunction.applyは同じではありません。

良い例では、すべての機能を持っている変数の引数であるあなたは、このようにその上に配列のメソッドを呼び出すことができますので、それは配列ではなく、配列のようなものですこの場合。

はのは、元の発信者が電話で

Foo.method(t, x, y, z) 

を呼び出し言うとJavaScriptガーデンのコードのように、一緒に適用してみましょう。これは、(アレイ表記でargumentsを書き込み、緩く)である

Function.call.apply(Foo.prototype.method, arguments); 

を実行する:呼び出す

Function.call.apply(Foo.prototype.method, [t, x, y, z]); 

Function.callthis==Foo.prototype.method有する:

tFoo.prototype.methodthisセットを呼び出す
Foo.prototype.method.call(t, x, y, z) 

引数:xy、およびz。甘い。ちょうどコメントのように。私たちはラッパーを作りました。

ここでは、Function.call.applyの代わりにちょうどFunction.applyと言っていますが、それは意味的に同等であると主張しています。あなたはthisFoo.prototype.methodと引数tに設定し、xy、およびzで機能Function(ぐふ!)を呼び出します(緩く)

Function.apply(Foo.prototype.method, [t, x, y, z]); 

ある

Function.apply(Foo.prototype.method, arguments); 

を持っているでしょう。

全く同じではありません。

+0

しかし、そのようなラッピングの目的は何ですか? – c69

+3

目的は、 'Foo.prototype.method'を' Foo'のインスタンスにバインドせずに呼び出すことです。代わりに、 'Foo.prototype.method'内の' this'の値として使用するために_your own_ valueを渡します。なぜあなたはこれをやりますか?たぶん、いくつかの関数型プログラミングをしたいと思うかもしれません。あなたがマップしたい、あるいは減らす、またはフィルタリングしたい関数がバウンドメソッドになるかもしれません。オブジェクトにバインドする必要がない場合は、「バインドされていないラッパー」を呼び出します。あなたが最終的にあなたのオブジェクトにこのメソッドをバインドしているので、これは奇妙な用語ですが(無視することができます....) –

+0

私が理解したところから、次のステートメントは同等です: Function.call.apply Foo.prototype.method、arguments); Foo.prototype.method.apply(arguments [0]、Array.prototype.slice.call(arguments、1)); 両方を置換して、バインドされていないラッパーを作成することができます。しかし、最初の方法は、より短く、より速く、より直感的です。驚くばかり! –

4

つまり、別のオブジェクトのメソッドを使用できます。

Array.prototype.join.call(arguments, ","); 
+1

しかし、 'apply'ビットは元の質問で何をしますか? –

+1

@CameronSkinner:関数オブジェクトの 'apply'メソッドは、最初の引数を' this'として扱い、2番目の引数を 'arguments'として扱います。 'fn.apply(a、[b、c])'は 'fn.call(a、b、c)'に相当します。 – eyelidlessness

関連する問題