Функціональні дзвінки
Функції - це лише тип Об'єкту.
Усі об'єкти Функції мають методи виклику та застосування, які виконують об'єкт Функції, до якого вони викликані.
При виклику перший аргумент цих методів вказує об'єкт, на який буде посилатися 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); }};