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