Le mot « fosse » signifie ici « piège ». En raison de la nature du « langage faible » de JavaScript, il est extrêmement lâche et flexible lors de son utilisation, mais il est également extrêmement facile de « tomber dans ces pièges ». caché , vous devez donc garder les yeux ouverts pour pouvoir voyager en douceur sur la voie de l'apprentissage et de l'application de JS
1. Variables globales
JavaScript gère la portée via des fonctions. Les variables déclarées à l'intérieur d'une fonction ne sont disponibles qu'à l'intérieur de la fonction et ne sont pas disponibles en dehors de la fonction. En revanche, les variables globales sont déclarées en dehors de toute fonction ou simplement utilisées sans être déclarées.
"Utilisation simple sans déclaration" fait référence à la déclaration de variables sans utiliser le mot-clé var. Nous le savons déjà très bien. Le moyen d’éviter de générer implicitement des variables globales est de déclarer autant que possible les variables en utilisant le mot-clé var.
Mais pensez-vous qu'utiliser var est acceptable ? Jetons un coup d'oeil à cette fosse :
function foo() {
var a = b = 0;
// corps...
}
Peut-être vous attendiez-vous à deux variables locales, mais b est une vraie variable globale. pourquoi ? Parce que les opérations d'affectation se font de droite à gauche, cela équivaut donc à :
function foo() {
var a = (b = 0);
// corps...
}
Donc b est une variable globale.
Remplissez le trou : déclarations de variables, il vaut mieux les faire une par une, ne pas faire en gros~_~;
2. Déclaration de variable
Regardons d'abord les pièges :
myName = "global";
function foo() {
alert(myName);
var myName = "local ";
alert(myName);
}
foo();
À première vue, on s'attend à ce que les résultats des deux alertes soient "globaux" et "locals ", mais le réel Les résultats sont "indéfinis" et "locals". pourquoi ? Étant donné que les variables sont dans la même portée (même fonction), les déclarations sont placées en haut de la portée et analysées en premier.
Le comportement d'exécution de l'extrait de code ci-dessus pourrait donc être le suivant :
function foo() {
var monNom;
alert(monNom); // "non défini"
monNom = "local";
alert(monNom); // "local"
}
Utilisez une autre fosse pour tester si vous comprenez vraiment la pré-analyse :
if (!("a" dans la fenêtre)) {
var a = 1;
}
alerte (a);
La déclaration d'une variable est avancée en haut du code et n'a pas encore reçu de valeur. Ensuite, entrez l'instruction if. La condition de jugement "a" dans la fenêtre a été établie (a a été déclarée comme variable globale), donc le résultat de l'évaluation de l'instruction de jugement est faux, et l'instruction if est sautée directement, donc l'instruction if. la valeur de a n’est pas définie.
var a; // "indéfini"
console .log("a" in window); // true
if (!("a" in window)) {
var a = 1; // Ne pas exécuter
>
alert(a); // "undefined"
Remplissez la fosse : déclaration de variable, il est préférable de la placer manuellement en haut de la portée Pour les variables qui ne peuvent pas l'être. attribué immédiatement, vous pouvez d'abord déclarer puis attribuer.
3. Déclaration de fonction
Les déclarations de fonctions sont également avancées en haut de la portée, analysées et évaluées avant toute expression et instruction
alert(typeof foo); // "function"
function foo() {
// body...
}
Vous pouvez comparer :
alert(typeof foo); // "indéfini"
var foo = function () {
// corps...
};
Après avoir compris cette vérité, tomberez-vous encore dans les pièges suivants ?
function test() {
alerte ("1");
}
test();
function test() {
alert("2");
}
test( );
Exécutez l'extrait de code ci-dessus et les deux fenêtres contextuelles que vous voyez affichent "2". Pourquoi ne sont-elles pas respectivement "1" et "2" ? Très simplement, la déclaration de test est analysée avant test(), et comme cette dernière écrase la première, le résultat des deux exécutions est "2".
Remplissez le trou : dans la plupart des cas, j'utilise des expressions de fonction au lieu de déclarations de fonction, en particulier dans certains blocs d'instructions.
4. Expressions de fonction
Regardons d'abord les expressions de fonction nommées Bien sûr, elles doivent avoir un nom, par exemple :
var bar = function foo() {
// body...
};
Il est à noter que le nom de la fonction n'est visible qu'à l'intérieur de sa fonction. Tels que les écueils suivants :
var bar = function foo() {
foo(); // Fonctionnement normal
};
foo(); // Erreur : ReferenceError
Remplissez le trou : utilisez le moins possible les expressions de fonctions nommées (sauf à des fins de récursivité et de débogage) et n'utilisez jamais de noms de fonctions en externe.
5. Auto-exécution des fonctions
Pour les expressions de fonction, vous pouvez vous auto-exécuter en ajoutant () après, et vous pouvez passer des paramètres entre parenthèses, mais les déclarations de fonction ne le peuvent pas. . Piège :
// (1) Ceci est juste un symbole d'opération de regroupement, pas un appel de fonction !
// Donc la fonction ici n'a pas été exécutée, c'est toujours une instruction
function foo(x) {
alert(x);
}(1);
Les extraits de code suivants sont respectivement La fenêtre contextuelle affiche "1" pendant l'exécution, car tout ce qui précède (1) est une expression de fonction, donc () ici n'est pas un opérateur de regroupement, mais un opérateur indiquant l'exécution de l'appel.
// Expression de fonction anonyme standard
var bar = function foo(x) {
alert(x);
}(1);
// Le précédent () convertit la déclaration de fonction en une expression
(function foo(x) {
alert(x);
})(1);
// Le tout () est l'expression
(function foo(x) {
alert(x) ;
}(1));
// nouvelle expression
nouvelle fonction foo(x) {
alert(x);
}(1);
// &&, ||, !, , -, ~ opérateurs (et virgules), lever l'ambiguïté des expressions de fonction et des déclarations de fonction
// donc une fois que l'analyseur sait que l'un d'eux est déjà une expression, et tout le reste est par défaut aux expressions
true && function foo(x) {
alert(x);
}(1);
Remplissez la fosse : cette fosse La clé est de comprendre l'essence de diverses expressions de fonctions.
6. Fermetures en boucles
Ce qui suit démontre un piège courant :
Copier le code Le code est le suivant :
Document lorsque vous cliquez sur les liens ci-dessous, affichez le numéro de sa séquence
< ;ul>
link #0 link #1 lien #2 lien n°3 lien n°4
var links = document.getElementsByTagName("ul")[ 0].getElementsByTagName("a");
for (var i = 0, l = links.length; i < l; i ) {
links[i].onclick = function (e ) {
e.preventDefault();
alert("Vous cliquez sur le lien #" i);
}
}
我们预期当点击第 i 个链接时,得到此序列索引 i 的值,可实际无论点击哪个链接,得到的都Et je 在循环后的最终结果:”5”。
解释一下原因:当 alerte 被调用时,pour 循环内的匿名函数表达式,保持了对外部变量 i的引用(闭包),此时循环已结束,i 的值被修改为 « 5 » 。
填坑 : 为了得到想要的结果 , 需要在每次循环中创建变量 i 的拷贝。以下演示正确的做法 :
Document lorsque vous cliquez sur les liens ci-dessous, affichez le nombre de sa séquence