La portée de JavaScript est délimitée par des fonctions, et différentes fonctions ont des portées relativement indépendantes. Les variables globales peuvent être déclarées et accessibles à l'intérieur de la fonction, et les variables locales peuvent également être déclarées (en utilisant le mot-clé var, les paramètres de la fonction sont également des variables locales), mais les variables locales internes ne sont pas accessibles en dehors de la fonction :
function test() { var a = 0; // 局部变量 b = 1; // 全局变量 } a = ?, b = ? // a为undefined,b为1
Les variables locales portant le même nom remplaceront les variables globales, mais ce sont essentiellement deux variables indépendantes. Les modifications apportées à l'une n'affecteront pas l'autre :
a = 5; // 函数外a的值为5 function test() { var a = 4; // 函数内a的值为4 }(); a = ? // 函数外a的值仍为5,不受函数影响
De manière générale, une fois la fonction terminée, toutes les références aux variables internes de la fonction se terminent, les variables locales au sein de la fonction seront recyclées et l'environnement d'exécution de la fonction sera effacé. Cependant, si la fonction interne est. utilisé comme résultat de retour de la fonction, la situation va changer :
function test(i) { var b = i * i; return function() { return b--; }; } var a = test(8); a(); // 返回值为64, 内部变量b为63 a(); // 返回值为63, 内部变量b为62
Lorsqu'une fonction interne est utilisée comme valeur de retour, parce que la référence à la variable interne ne se termine pas après la fin de la fonction, les variables locales de la fonction ne peuvent pas être recyclées et l'environnement d'exécution de la fonction est conservé, ainsi formant un effet de fermeture, qui peut être transmis Accès de référence aux variables internes qui doivent être recyclées.
La fermeture rend également les variables locales de la fonction des variables « privées », accessibles uniquement via la fonction interne renvoyée et ne pouvant être modifiées par aucun autre moyen.
Par conséquent, les fermetures peuvent être utilisées pour conserver les variables locales et protéger les variables.
Sans fermeture :
var a = []; // 假设a中包含5个元素 for (var i = 0, m = a.length; i < m; i++) { a[i].onclick = function(e) { return 'No. ' + i; }; } // 点击任何一个元素,返回值都是“No. 5”,因为i最后的值为5 使用闭包的情况: function test(i) { return function(e) { return 'No. ' + i; }; } var a = []; // 假设a中包含5个元素 for (var i = 0, m = a.length; i < m; i++) { a[i].onclick = test(i); } // 使用闭包维持局部变量,点击元素返回No. 0 ~ No. 4
Bien que les fermetures apportent de la commodité, elles présentent également certains inconvénients :
1. La complexité du programme augmente et il devient plus difficile à comprendre
2. Interférant avec la collecte normale des déchets, des fermetures complexes peuvent également entraîner l'échec du recyclage de la mémoire et un crash
3. Les fermetures énormes s'accompagnent souvent de problèmes de performances
Par conséquent, les fermetures doivent être compactes et compactes, plutôt que grandes et complexes, et leur utilisation à grande échelle doit être évitée. L’émergence des fermetures est en soi un bug du langage, mais il demeure en raison de ses fonctions uniques. Il s'agit d'un moyen supplémentaire et non de la fonction principale.