Chaque fois que vous voyez le mot clé de fonction dans une autre fonction, la fonction interne a accès aux variables de la fonction externe.
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp)); // will alert 16
}
bar(10);
}
foo(2);
Ce sera toujours en alerte 16, car bar
pouvez accéder à l' x
qui a été défini comme un argument à l' foo
, et il peut également accéder tmp
de foo
.
C' est une fermeture. Une fonction n'a pas de retour afin d'être appelé à la fermeture. Tout simplement l'accès aux variables hors de votre portée lexicale crée une fermeture.
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp)); // will also alert 16
}
}
var bar = foo(2); // bar is now a closure.
bar(10);
La fonction ci-dessus également d'alerter 16, car bar
pouvez toujours vous y référer x
et tmp
, même si elle n'est plus directement à l'intérieur de la portée.
Cependant, depuis tmp
est toujours traîner à l'intérieur d' bar
's la fermeture, c'est aussi d'être augmentés. Il sera incrémenté chaque fois que vous appelez bar
.
L'exemple le plus simple d'une fermeture est ceci:
var a = 10;
function test() {
console.log(a); // will output 10
console.log(b); // will output 6
}
var b = 6;
test();
Lorsqu'une fonction JavaScript est exécuté, un nouveau contexte d'exécution est créé. Avec les arguments de la fonction et de l'objet parent, ce contexte d'exécution reçoit également toutes les variables déclarées en dehors d'elle (dans l'exemple ci-dessus, à la fois 'a' et 'b').
Il est possible de créer plus d'une fonction de clôture, soit par le retour d'une liste d'entre eux ou par l'établissement à des variables globales. Tous ces éléments vont se référer à la même x
et le même tmp
, ils ne font pas leurs propres copies.
Ici, le nombre x
est un nombre littéral. Comme avec d'autres littéraux en JavaScript, lorsqu' foo
est appelé, le nombre x
est copié en foo
comme argument x
.
D'autre part, JavaScript utilise toujours des références lorsque vous traitez avec des Objets. Si par exemple, vous avez appelé foo
avec un Objet, la fermeture il rendements de référence que l'Objet d'origine!
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);
Comme prévu, chaque appel à l' bar(10)
incrémente x.memb
. Ce peut-être pas prévu, c'est qu' x
est tout simplement référence au même objet que l' age
variable! Après quelques appels à bar
, age.memb
2! Ce référencement est la base pour les fuites de mémoire avec des objets HTML.