Dans l'introduction précédente, nous savons déjà que JavaScript n'a pas de fonction au niveau de bloc, uniquement la portée au niveau de la fonction.
La copie de code est la suivante:
fonction de fonction () {// une portée
pour (var i = 0; i <10; i ++) {// pas une portée
// compter
}
console.log (i); // 10
}
Il n'y a pas non plus d'espace de noms affiché dans JavaScript, ce qui signifie que tout est défini dans la portée globale. Chaque fois qu'une variable est référencée, JavaScript traversera toute la portée globale jusqu'à ce qu'elle soit trouvée. Si la variable n'est toujours pas trouvée à travers la portée globale complète, une erreur de référence est lancée.
Veuillez saisir une description de l'image
Variables globales implicites
La copie de code est la suivante:
// script a
foo = '42';
// Script B
var foo = '42'
Les deux exemples ci-dessus ont des effets différents. Le premier définira la variable FOO dans la portée globale, tandis que la seconde définira la variable FOO dans la portée actuelle.
Nous devons noter que si vous n'utilisez pas le mot-clé VAR, il aura un impact inattendu.
La copie de code est la suivante:
// Portée mondiale
var foo = 42;
fonction test () {
// Portée locale
foo = 21;
}
test();
foo; // 21
Étant donné que VAR n'est pas utilisé pour définir la variable FOO dans le test de fonction, la variable globale FOO en dehors de la fonction sera écrasée. Bien que cela ne semble pas être un gros problème, s'il y a des milliers de lignes de code, ce sera un bug difficile à suivre.
La copie de code est la suivante:
// Portée mondiale
var items = [/ * une liste * /];
pour (var i = 0; i <10; i ++) {
Subop ();
}
fonction sulolop () {
// Portée de Subop
pour (i = 0; i <10; i ++) {// Instruction var manquante
// Faites des trucs incroyables!
}
}
Dans l'exemple ci-dessus, la boucle externe s'arrêtera lorsque la première exécution est exécutée, car la variable I à l'intérieur de la fonction Subloop remplacera la variable globale externe i. Nous n'avons qu'à ajouter un VAR à l'intérieur de la fonction pour éviter cette erreur, nous ne devons donc pas oublier d'ajouter le mot-clé VAR lors de la définition des variables. Sauf si nous voulons avoir un impact sur les variables globales externes.
Variables locales
Les variables locales dans JavaScript ne peuvent être générées que de deux manières, l'une est déclarée via le mot-clé VAR, et l'autre est utilisé comme paramètres formels de la fonction.
La copie de code est la suivante:
// Portée mondiale
var foo = 1;
var bar = 2;
var i = 2;
Test de fonction (i) {
// Étendue locale du test de fonction
i = 5;
var foo = 3;
bar = 4;
}
test (10);
À l'heure actuelle, les variables I et FOO à l'intérieur du test de fonction sont des variables locales, et la barre remplacera la barre variable globale externe.
Hissage
JavaScript favorisera les déclarations variables, ce qui signifie que les expressions VAR et les déclarations de fonction seront promues en haut de la portée.
La copie de code est la suivante:
bar();
var bar = function () {};
var someValue = 42;
test();
Test de fonction (données) {
if (false) {
goo = 1;
} autre {
var goo = 2;
}
pour (var i = 0; i <100; i ++) {
var e = data [i];
}
}
Avant l'exécution du code ci-dessus, la déclaration d'expression VAR et le test de fonction sera promue en haut, de sorte que le programme s'exécutera normalement et ne rapportera pas d'erreur.
La copie de code est la suivante:
// les déclarations var ont été déplacées ici
Var Bar, quelque valeur de valeur; // par défaut «Undefined»
// La déclaration de fonction a également été éloignée
Test de fonction (données) {
var goo, i, e; // La portée du bloc manquante les déplace ici
if (false) {
goo = 1;
} autre {
goo = 2;
}
pour (i = 0; i <100; i ++) {
e = data [i];
}
}
bar(); // échoue avec un type EERROR car la barre n'est toujours pas définie "
SomeValue = 42; // Les affectations ne sont pas affectées par le hissage
bar = function () {};
test();
Étant donné que JavaScript n'a pas de portée au niveau du bloc, cela améliorera non seulement l'expression VAR, mais rendra également la structure IF moins intuitive.
Dans l'exemple ci-dessus, bien qu'il semble que si fonctionne sur la variable globale GOO, en fait, puisque la variable GOO est promue, la variable locale est modifiée.
Si vous n'avez aucune compréhension des règles d'élévation, vous pouvez penser que le code suivant lancera une erreur de référence.
La copie de code est la suivante:
// Vérifiez si quelque chose d'important a été initialisé
if (! Some Important therch) {
var some Importantthing = {};
}
Bien sûr, le code ci-dessus n'est pas faux, car l'expression VAR a été promue en haut avant l'exécution du code.
La copie de code est la suivante:
var quelque chose d'important;
// autre code peut initialiser quelque chose d'important ici, ou non
// Assurez-vous qu'il est là
if (! Some Important therch) {
Some ImportantThing = {};
}
Ici, je voudrais recommander le article de blog de @nightire fan GE "Comprendre JavaScript (II)", qui explique l'amélioration de manière très approfondie.
Ordre de résolution du nom
Lorsque vous essayez d'accéder à une variable FOO dans une portée de fonction, JavaScript le recherchera dans l'ordre suivant:
S'il y a une définition de var foo dans la portée actuelle.
S'il existe une variable FOO dans le paramètre de fonction.
Si la fonction elle-même est foo.
Sautez dans le domaine de définition externe et commencez à rechercher la première partie.
Espace de noms
L'un des problèmes les plus courants est de nommer les conflits, car JavaScript n'a qu'une seule portée mondiale. Mais ce problème peut être résolu par des fonctions externes anonymes.
La copie de code est la suivante:
(fonction() {
// un "espace de noms" autonome
window.foo = function () {
// une fermeture exposée
};
}) (); // Exécuter la fonction immédiatement
Les fonctions anonymes dans l'exemple ci-dessus sont considérées comme des expressions, donc elles sont exécutées.
La copie de code est la suivante:
(// évaluer la fonction à l'intérieur des parents
fonction() {}
) // et renvoyer l'objet de fonction
() // appelle le résultat de l'évaluation
Bien sûr, nous pouvons également utiliser d'autres méthodes pour appeler les expressions de fonction, différentes structures, mais le même effet.
La copie de code est la suivante:
// quelques autres styles pour invoquer directement le
!fonction(){}()
+ function () {} ()
(fonction(){}());
// et ainsi de suite...
Résumer
Il est recommandé d'utiliser des fonctions externes anonymes pour résumer le code dans l'espace, ce qui résout non seulement les conflits d'espace de noms, mais facilite également la modularisation du programme.
De plus, l'utilisation de variables globales n'est pas une bonne habitude, ce qui entraînera des coûts d'entretien élevés et est sujet aux erreurs.
Les espaces de noms ont les mêmes types, fonctions, variables, modèles, etc., tous appartiennent à des entités.
Le principal point commun d'une entité est qu'il peut avoir un nom. (De plus, une balise peut également avoir un nom, mais ce n'est pas une entité.)
La portée de l'espace de noms est un terme général dans la portée, qui est parallèle à la portée du bloc, à la portée de la classe, à la portée du prototype de fonction et à la portée de la fonction (uniquement valide pour les étiquettes). Les noms déclarés dans l'espace de noms sont dans la portée de l'espace de noms. Les noms globaux sont pris en compte dans la portée implicite de l'espace de noms global.
La fonction d'un espace de noms est en effet de la portée, mais elle est différente d'une portée simple. Vous pouvez déclarer le même espace de noms à plusieurs endroits à plusieurs reprises, mais le contenu à l'intérieur ne peut pas être redéfini. Ils finiront par synthétiseront un espace de noms, tout comme la MST, les définitions macro partout.