関数呼び出し
関数はオブジェクトの一種です。
すべての Function オブジェクトには、呼び出された Function オブジェクトを実行するcallメソッドとapplyメソッドがあります。
呼び出されると、これらのメソッドの最初の引数thisは、関数の実行中にキーワードによって参照されるオブジェクトを指定しnullます。undefinedwindowthis
したがって、関数を呼び出す...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
...括弧付き - - はorfoo()と同等で、実質的にorと同じです。foo.call(undefined)foo.apply(undefined)foo.call(window)foo.apply(window)
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
への追加callの引数は引数として関数呼び出しに渡されますが、への追加の引数は 1 つだけapplyで、関数呼び出しの引数を配列のようなオブジェクトとして指定できます。
したがって、はまたはfoo(1, 2, 3)と同等です。foo.call(null, 1, 2, 3)foo.apply(null, [1, 2, 3])
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
関数がオブジェクトのプロパティである場合...
var obj =
{
whereAmI: "obj",
foo: foo
};
...オブジェクトを介して Function への参照にアクセスし、括弧を付けて呼び出すことは、 orobj.foo()と同等です。foo.call(obj)foo.apply(obj)
ただし、オブジェクトのプロパティとして保持される関数は、それらのオブジェクトに「バインド」されません。上記の定義でわかるobjように、関数は単なるオブジェクトの型であるため、参照できます (したがって、関数呼び出しへの参照によって渡されるか、関数呼び出しからの参照によって返されます)。関数への参照が渡されると、それがどこから渡されたかに関する追加情報は一緒に運ばれません。そのため、次のことが起こります。
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
関数参照 へbazの呼び出しは、呼び出しのコンテキストを提供しないため、実質的に と同じでbaz.call(undefined)あり、最終的にthisを参照しますwindow。bazそれが に属していることを知りたい場合は、 が呼び出されobjたときに何らかの方法でその情報を提供する必要があります。これは、 orおよびクロージャーbazの最初の引数が作用する場所です。callapply
スコープチェーン
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
関数が実行されると、新しいスコープが作成され、外側のスコープへの参照が含まれます。上記の例で無名関数が作成されると、作成されたスコープ ( のスコープ) への参照が含まれbindます。これは「閉鎖」として知られています。
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
変数にアクセスしようとすると、この「スコープ チェーン」がウォークされて、指定された名前の変数が検索されます。現在のスコープに変数が含まれていない場合は、チェーン内の次のスコープが調べられ、到達するまで続きます。グローバルスコープ。匿名関数が返されて実行が終了しても、匿名関数はのスコープへのbind参照を保持しているため、のスコープは「消えません」。bindbind
上記のすべてを考えると、次の例でスコープがどのように機能するか、および特定の値を使用して「事前にバインド」された関数を渡す手法thisが呼び出されたときに機能する理由を理解できるはずです。
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"