Далее следует выдержка из книги «Закрытие: полное руководство» Майкла Болина . Это может выглядеть немного длинным, но оно насыщено глубоким пониманием. Из «Приложения Б. Часто неверно понимаемые концепции 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применении к массиву аргументов иcвызове столбцов с аргументами.