Panggilan fungsi
Fungsi hanyalah jenis Objek.
Semua objek fungsi memiliki panggilan dan menerapkan metode yang mengeksekusi objek fungsi mereka dipanggil.
Saat dipanggil, argumen pertama ke metode ini menentukan objek yang akan direferensikan oleh this
kata kunci selama eksekusi Fungsi - apakah itu null
atau undefined
, objek global window
, digunakan untuk this
.
Dengan demikian, memanggil Fungsi ...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
... dengan tanda kurung - foo()
- sama dengan foo.call(undefined)
atau foo.apply(undefined)
, yang secara efektif sama dengan foo.call(window)
atau foo.apply(window)
.
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
Argumen tambahan untuk call
diteruskan sebagai argumen untuk panggilan fungsi, sedangkan argumen tambahan tunggal untuk apply
dapat menentukan argumen untuk panggilan fungsi sebagai objek seperti Array.
Dengan demikian, foo(1, 2, 3)
sama dengan foo.call(null, 1, 2, 3)
atau 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"
Jika suatu fungsi adalah properti dari suatu objek ...
var obj =
{
whereAmI: "obj",
foo: foo
};
... mengakses referensi ke Fungsi melalui objek dan memanggilnya dengan tanda kurung - obj.foo()
- sama dengan foo.call(obj)
atau foo.apply(obj)
.
Namun, fungsi yang dipegang sebagai properti objek tidak "terikat" pada objek tersebut. Seperti yang dapat Anda lihat dalam definisi di obj
atas, karena Fungsi hanyalah jenis Objek, mereka dapat dirujuk (dan dengan demikian dapat diteruskan dengan referensi ke Panggilan fungsi atau dikembalikan dengan referensi dari Panggilan fungsi). Ketika referensi ke Fungsi dilewatkan, tidak ada informasi tambahan tentang di mana ia lulus dari dilakukan dengan itu, yang mengapa terjadi berikut:
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
Panggilan ke referensi Fungsi kami baz
,, tidak memberikan konteks apa pun untuk panggilan tersebut, jadi itu sama dengan baz.call(undefined)
, jadi pada this
akhirnya merujuk window
. Jika kita ingin baz
tahu bahwa itu milik obj
, kita perlu entah bagaimana memberikan informasi itu ketika baz
dipanggil, yang merupakan tempat argumen pertama call
atau apply
dan penutupan ikut bermain.
Rantai ruang lingkup
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
Ketika suatu Fungsi dieksekusi, ia menciptakan suatu lingkup baru dan memiliki referensi ke segala lingkup yang melampirkan. Ketika fungsi anonim dibuat dalam contoh di atas, ia memiliki referensi ke ruang lingkup itu dibuat, yang merupakan bind
ruang lingkup. Ini dikenal sebagai "penutupan."
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
Ketika Anda mencoba mengakses variabel ini, "rantai lingkup" ini berjalan untuk menemukan variabel dengan nama yang diberikan - jika cakupan saat ini tidak mengandung variabel, Anda melihat cakupan berikutnya dalam rantai, dan seterusnya hingga Anda mencapai ruang lingkup global. Ketika fungsi anonim dikembalikan dan bind
selesai dieksekusi, fungsi anonim masih memiliki referensi ke bind
ruang lingkup, jadi bind
ruang lingkup tidak "hilang".
Dengan semua hal di atas, Anda sekarang harus dapat memahami bagaimana ruang lingkup bekerja dalam contoh berikut, dan mengapa teknik untuk melewatkan fungsi di sekitar "pra-terikat" dengan nilai tertentu this
akan memilikinya ketika disebut bekerja:
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
var signup = { onLoadHandler:function(){ console.log(this); return Type.createDelegate(this,this._onLoad); }, _onLoad: function (s, a) { console.log("this",this); }};