Następuje fragment z Closure: The Definitive Guide autorstwa Michaela Bolina . Może wydawać się nieco długi, ale jest nasycony dużą ilością wglądu. Z „Dodatku B. Często źle rozumiane pojęcia JavaScript”:
Co thisdotyczy wywołania funkcji
Podczas wywoływania funkcji formularza foo.bar.baz()obiekt foo.barnazywany jest odbiorcą. Gdy funkcja jest wywoływana, odbiornik jest używany jako wartość dla 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);
Jeśli po wywołaniu funkcji nie ma jawnego odbiornika, wówczas obiekt globalny staje się odbiorcą. Jak wyjaśniono w „goog.global” na stronie 47, okno jest obiektem globalnym, gdy JavaScript jest uruchamiany w przeglądarce internetowej. Prowadzi to do zaskakujących zachowań:
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
Chociaż obj.addValuesi fodnoszą się do tej samej funkcji, zachowują się inaczej, gdy nazywa ponieważ wartość odbiornika jest inna w każdej rozmowie. Z tego powodu przy wywoływaniu funkcji, do której się thisona odnosi , ważne jest, aby upewnić się, że thisbędzie miała poprawną wartość, gdy zostanie wywołana. Dla jasności, gdyby thisnie odwoływać się do treści funkcji, zachowanie f(20)i obj.addValues(20)byłoby takie samo.
Ponieważ funkcje są pierwszorzędnymi obiektami w JavaScript, mogą mieć własne metody. Wszystkie funkcje mają metody call()i apply()które pozwalają na ponowne zdefiniowanie odbiornik (czyli obiekt, który thisodnosi się do) przy wywołaniu funkcji. Podpisy metod są następujące:
/**
* @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;
Zauważ, że jedyna różnica między call()i apply()polega na tym, że call()odbiera parametry funkcji jako poszczególne argumenty, podczas gdy apply()odbiera je jako pojedynczą tablicę:
// 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]);
Następujące wywołania są równoważne fi obj.addValuesodnoszą się do tej samej funkcji:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
Ponieważ jednak ani call()nie apply()używa wartości własnego odbiornika do zastąpienia argumentu odbiorcy, gdy nie jest on określony, następujące działania nie będą działać:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
Wartość thisnigdy nie może być nulllub undefinedgdy funkcja jest wywoływana. Gdy nulllub undefinedjest dostarczane jako odbiornik do call()lub apply(), zamiast tego używany jest obiekt globalny jako wartość dla odbiornika. Dlatego poprzedni kod ma ten sam niepożądany efekt uboczny dodawania właściwości o nazwie valuedo obiektu globalnego.
Pomocne może być myślenie o funkcji jako nie posiadającej wiedzy o zmiennej, do której jest przypisana. Pomaga to wzmocnić ideę, że wartość tego będzie ograniczona, gdy funkcja zostanie wywołana, a nie kiedy zostanie zdefiniowana.
Koniec wyciągu.
aw przypadku ubiegania się o tablicę argów icwzywając do kolumn arg.