関数呼び出し
関数はオブジェクトの一種です。
すべての Function オブジェクトには、呼び出された Function オブジェクトを実行するcallメソッドとapplyメソッドがあります。
呼び出されると、これらのメソッドの最初の引数this
は、関数の実行中にキーワードによって参照されるオブジェクトを指定しnull
ます。undefined
window
this
したがって、関数を呼び出す...
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
の最初の引数が作用する場所です。call
apply
スコープチェーン
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
参照を保持しているため、のスコープは「消えません」。bind
bind
上記のすべてを考えると、次の例でスコープがどのように機能するか、および特定の値を使用して「事前にバインド」された関数を渡す手法this
が呼び出されたときに機能する理由を理解できるはずです。
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"