Дотримується витяг із закриття: Посібник з остаточного значення Майкла Боліна . Це може виглядати трохи затяжно, але воно насичене багато розуміння. З "Додаток B. Часто невідомі поняття JavaScript":
Що this
стосується виклику функції
При виклику функції форми foo.bar.baz()
об’єкт foo.bar
називається приймачем. Коли функція викликається, саме приймач використовується як значення для this
:
var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
for (var i = 0; i < arguments.length; i++) {
this.value += arguments[i];
}
return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);
Якщо при виклику функції немає явного приймача, то глобальним об'єктом стає приймач. Як пояснено в "goog.global" на сторінці 47, вікно - це глобальний об'єкт, коли JavaScript виконується у веб-браузері. Це призводить до деякої дивної поведінки:
var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN
Незважаючи на те , що вони посилаються на одну obj.addValues
і f
ту ж функцію, вони поводяться по-різному при виклику, оскільки значення приймача різне в кожному дзвінку. З цієї причини при виклику функції, на яку посилається this
, важливо переконатися, що this
буде мати правильне значення при її виклику . Щоб було зрозуміло, якби this
не посилалися на функціональний орган, то поведінка f(20)
та obj.addValues(20)
була б однаковою.
Оскільки функції є першокласними об'єктами в JavaScript, вони можуть мати свої власні методи. Всі функції мають методи call()
і apply()
які дають можливість перевизначити приймач (тобто об'єкт , який this
відноситься до) при виконанні функції. Метод підписів такий:
/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;
Зауважимо, що єдина різниця між call()
і apply()
полягає в тому, що вони call()
отримують параметри функції як окремі аргументи, тоді як apply()
отримує їх як єдиний масив:
// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);
Наступні дзвінки еквівалентні, як f
і obj.addValues
відносяться до тієї ж функції:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
Однак, оскільки call()
ані apply()
використовує значення власного приймача для заміни аргументу приймача, коли він не визначений, наступне не буде працювати:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
Значення " this
ніколи не може бути null
або undefined
коли викликається функція". Коли null
або undefined
подається в якості приймача до call()
або apply()
, глобальний об'єкт використовується як значення для приймача. Тому попередній код має той самий небажаний побічний ефект від додавання властивості, названого value
до глобального об'єкта.
Може бути корисно думати про функцію як про відсутність знань про змінну, якій вона призначена. Це допомагає посилити думку про те, що значення цього значення буде пов'язане, коли функція викликається, а не коли вона визначається.
Кінець витягу.
a
застосуйте для масиву args таc
зателефонуйте до стовпців.