Функціональні дзвінки
Функції - це лише тип Об'єкту.
Усі об'єкти Функції мають методи виклику та застосування, які виконують об'єкт Функції, до якого вони викликані.
При виклику перший аргумент цих методів вказує об'єкт, на який буде посилатися this
ключове слово під час виконання функції - якщо він використовується, null
або undefined
, глобальний об'єкт, window
використовується this
.
Таким чином, виклик функції ...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
... з дужками - foo()
- еквівалентно 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
передаються як аргументи до виклику функції, тоді як єдиний додатковий аргумент, який 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
};
... доступ до посилання на функцію через об'єкт та виклик його в дужках - obj.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
, нам потрібно якимось - то чином надати цю інформацію , коли 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
's, тому bind
область дії не «відходить».
З огляду на все вищесказане, тепер ви зможете зрозуміти, як працює область в наступному прикладі, і чому техніка передачі функції навколо "попередньо пов'язаної" з певним значенням this
її буде мати, коли вона називається працює:
>>> 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); }};