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 thiskata kunci selama eksekusi Fungsi - apakah itu nullatau 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 callditeruskan sebagai argumen untuk panggilan fungsi, sedangkan argumen tambahan tunggal untuk applydapat 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 objatas, 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 thisakhirnya merujuk window. Jika kita ingin baztahu bahwa itu milik obj, kita perlu entah bagaimana memberikan informasi itu ketika bazdipanggil, yang merupakan tempat argumen pertama callatau applydan 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 bindruang 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 bindselesai dieksekusi, fungsi anonim masih memiliki referensi ke bindruang lingkup, jadi bindruang 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 thisakan 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); }};