Maison interface Web js tutoriel Série JavaScript Advanced : portée et espace de noms

Série JavaScript Advanced : portée et espace de noms

Feb 08, 2017 am 09:35 AM

  • Variables globales implicites

  • Variables locales

  • Levage de déclaration de variable (Hoisting)

  • Ordre de résolution de nom

  • Espace de noms

  • Conclusion

Bien que JavaScript prenne en charge les extraits de code créés par une paire d'accolades, il ne prend pas en charge la portée au niveau du bloc ; seule la portée de la fonction est prise en charge.

function test() { // 一个作用域
    for(var i = 0; i < 10; i++) { // 不是一个作用域
        // count
    }
    console.log(i); // 10
}
Copier après la connexion

Note du traducteur : si le crochet gauche de l'objet return et return ne sont pas sur la même ligne, une erreur se produira.

(Remarque : s'il ne se trouve pas dans une instruction d'affectation, mais dans une expression de retour ou un paramètre de fonction, {...} sera analysé comme un segment de code, et non comme une analyse syntaxique littérale de l'objet . Si l'insertion automatique d'un point-virgule est prise en compte, cela peut conduire à des erreurs subtiles)

// 译者注:下面输出 undefined
function add(a, b) {
    return 
        a + b;
}
console.log(add(1, 2));
Copier après la connexion

Il n'y a pas de définition explicite d'espace de noms en JavaScript, ce qui signifie que tous les objets sont définis sous. un espace de noms partagé à l’échelle mondiale.

Chaque fois qu'une variable est référencée, JavaScript parcourra toute la portée vers le haut jusqu'à ce qu'il trouve la variable. Si la portée globale est atteinte mais que la variable n'est toujours pas trouvée, une exception ReferenceError est levée.

Variables globales implicites

// 脚本 A
foo = &#39;42&#39;;

// 脚本 B
var foo = &#39;42&#39;
Copier après la connexion

Les deux scripts ci-dessus ont des effets différents. Le script A définit la variable foo dans la portée globale, tandis que le script B définit la variable foo dans la portée actuelle.

Encore une fois, l'effet ci-dessus est complètement différent. Déclarer des variables sans utiliser var entraînera la création de variables globales implicites.

// 全局作用域
var foo = 42;
function test() {
    // 局部作用域
    foo = 21;
}
test();
foo; // 21
Copier après la connexion

Déclarer la variable foo sans utiliser le mot-clé var dans le test de fonction écrasera la variable externe du même nom. Cela peut ne pas sembler être un gros problème au début, mais lorsque vous avez des milliers de lignes de code, déclarer des variables sans utiliser var peut conduire à des bugs difficiles à détecter.

// 全局作用域
var items = [/* 数组 */];
for(var i = 0; i < 10; i++) {
    subLoop();
}

function subLoop() {
    // subLoop 函数作用域
    for(i = 0; i < 10; i++) { // 没有使用 var 声明变量
        // 干活
    }
}
Copier après la connexion

La boucle externe se terminera après le premier appel à subLoop car subLoop écrase la variable globale i. Cette erreur peut être évitée en déclarant la variable en utilisant var dans la deuxième boucle for. N'omettez jamais le mot-clé var lors de la déclaration d'une variable, sauf s'il s'agit du comportement souhaité affectant la portée externe.

Variables locales

Les variables locales en JavaScript ne peuvent être déclarées que de deux manières, l'une en tant que paramètre de fonction, l'autre est déclarée via le mot-clé var.

// 全局变量
var foo = 1;
var bar = 2;
var i = 2;

function test(i) {
    // 函数 test 内的局部作用域
    i = 5;

    var foo = 3;
    bar = 4;
}
test(10);
Copier après la connexion

foo et i sont des variables locales dans la fonction test, et l'affectation à bar écrasera la variable du même nom dans la portée globale.

Histage des déclarations de variables (Hoisting)

JavaScript lèvera les déclarations de variables. Cela signifie que les expressions var et les déclarations de fonction seront hissées en haut de la portée actuelle.

bar();
var bar = function() {};
var someValue = 42;

test();
function test(data) {
    if (false) {
        goo = 1;

    } else {
        var goo = 2;
    }
    for(var i = 0; i < 100; i++) {
        var e = data[i];
    }
}
Copier après la connexion

Le code ci-dessus sera converti avant son exécution. JavaScript hissera les expressions var et les déclarations de fonctions en haut de la portée actuelle.

// var 表达式被移动到这里
var bar, someValue; // 缺省值是 &#39;undefined&#39;

// 函数声明也会提升
function test(data) {
    var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
    if (false) {
        goo = 1;

    } else {
        goo = 2;
    }
    for(i = 0; i < 100; i++) {
        e = data[i];
    }
}

bar(); // 出错:TypeError,因为 bar 依然是 &#39;undefined&#39;
someValue = 42; // 赋值语句不会被提升规则(hoisting)影响
bar = function() {};

test();
Copier après la connexion

Ne pas avoir de portée de bloc entraîne non seulement le déplacement des expressions var de l'intérieur de la boucle vers l'extérieur, mais rend également certaines expressions if plus difficiles à lire.

Dans le code original, l'expression if semble modifier la variable globale goo, mais en fait elle modifie la variable locale après l'application de la règle de promotion.

Sans connaissance du levage, le code suivant semble lever une exception ReferenceError.

// 检查 SomeImportantThing 是否已经被初始化
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}
Copier après la connexion

En fait, le code ci-dessus fonctionne bien car l'expression var est hissée au sommet de la portée globale.

var SomeImportantThing;

// 其它一些代码,可能会初始化 SomeImportantThing,也可能不会

// 检查是否已经被初始化
if (!SomeImportantThing) {
    SomeImportantThing = {};
}
Copier après la connexion

Note du traducteur : il existe un article présentant le levage sur le site Web de Nettuts, et le code qu'il contient est très instructif.

// 译者注:来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
var myvar = &#39;my value&#39;;  

(function() {  
    alert(myvar); // undefined  
    var myvar = &#39;local value&#39;;  
})();
Copier après la connexion

Ordre de résolution des noms


Toutes les étendues en JavaScript, y compris la portée globale, ont un nom spécial qui pointe vers l'objet actuel. Il existe également une variable par défaut arguments dans la portée de la fonction, qui contient les paramètres transmis à la fonction. Par exemple, lors de l'accès à la variable foo dans une fonction, JavaScript recherchera dans l'ordre suivant :

  1. S'il existe une définition de var foo dans la portée actuelle.

  2. Si les paramètres formels de la fonction utilisent le nom foo.

  3. Si la fonction elle-même s'appelle foo.

  4. Retournez à la portée précédente et recommencez à partir du n°1.

Espace de noms

Une erreur courante causée par le fait de n'avoir qu'une seule portée globale est les conflits de noms. En JavaScript, cela peut être facilement résolu avec des wrappers anonymes.

(Remarque : les paramètres d'arguments personnalisés empêcheront la création d'objets d'arguments natifs.)

(function() {
    // 函数创建一个命名空间

    window.foo = function() {
        // 对外公开的函数,创建了闭包
    };

})(); // 立即执行此匿名函数
Copier après la connexion

Les fonctions anonymes sont considérées comme des expressions ; par conséquent, pour l'appel, elles doivent d'abord être exécutées.

( // 小括号内的函数首先被执行
function() {}
) // 并且返回函数对象
() // 调用上面的执行结果,也就是函数对象
Copier après la connexion

Il existe d'autres façons d'appeler des expressions de fonction. Par exemple, les deux méthodes suivantes ont une syntaxe différente, mais l'effet est exactement le même.

// 另外两种方式
+function(){}();
(function(){}());
Copier après la connexion

Conclusion


Il est recommandé d'utiliser des wrappers anonymes (Note du traducteur : fonctions anonymes auto-exécutables) pour créer des espaces de noms. Cela évite non seulement les conflits de noms, mais facilite également la modularisation du programme.

De plus, l'utilisation de variables globales est considérée comme une mauvaise pratique. Un tel code est sujet aux erreurs et coûteux à maintenir.

Ce qui précède est le contenu de la série avancée JavaScript - portée et espace de noms. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !


Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Utilisation de la structure typedef en langage C Utilisation de la structure typedef en langage C May 09, 2024 am 10:15 AM

typedef struct est utilisé en langage C pour créer des alias de type de structure afin de simplifier l'utilisation des structures. Il crée un alias pour un nouveau type de données sur une structure existante en spécifiant l'alias de la structure. Les avantages incluent une lisibilité améliorée, la réutilisation du code et la vérification du type. Remarque : La structure doit être définie avant d'utiliser un alias. L'alias doit être unique dans le programme et valide uniquement dans le périmètre dans lequel il est déclaré.

Comment résoudre la variable attendue en Java Comment résoudre la variable attendue en Java May 07, 2024 am 02:48 AM

Les exceptions de valeur attendue des variables en Java peuvent être résolues en : initialisant les variables ; en utilisant des valeurs par défaut ; en utilisant des contrôles et des affectations et en connaissant la portée des variables locales ;

Avantages et inconvénients des fermetures en js Avantages et inconvénients des fermetures en js May 10, 2024 am 04:39 AM

Les avantages des fermetures JavaScript incluent le maintien d'une portée variable, l'activation du code modulaire, l'exécution différée et la gestion des événements ; les inconvénients incluent les fuites de mémoire, la complexité accrue, la surcharge de performances et les effets de chaîne de portée.

Que signifie inclure en C++ Que signifie inclure en C++ May 09, 2024 am 01:45 AM

La directive de préprocesseur #include en C++ insère le contenu d'un fichier source externe dans le fichier source actuel, en copiant son contenu à l'emplacement correspondant dans le fichier source actuel. Principalement utilisé pour inclure des fichiers d'en-tête contenant les déclarations nécessaires dans le code, telles que #include <iostream> pour inclure des fonctions d'entrée/sortie standard.

Pointeurs intelligents C++ : une analyse complète de leur cycle de vie Pointeurs intelligents C++ : une analyse complète de leur cycle de vie May 09, 2024 am 11:06 AM

Cycle de vie des pointeurs intelligents C++ : Création : Les pointeurs intelligents sont créés lors de l'allocation de mémoire. Transfert de propriété : Transférer la propriété via une opération de déménagement. Libération : la mémoire est libérée lorsqu'un pointeur intelligent sort de la portée ou est explicitement libéré. Destruction d'objet : lorsque l'objet pointé est détruit, le pointeur intelligent devient un pointeur invalide.

Les définitions de fonctions et les appels en C++ peuvent-ils être imbriqués ? Les définitions de fonctions et les appels en C++ peuvent-ils être imbriqués ? May 06, 2024 pm 06:36 PM

Peut. C++ autorise les définitions et les appels de fonctions imbriquées. Les fonctions externes peuvent définir des fonctions intégrées et les fonctions internes peuvent être appelées directement dans la portée. Les fonctions imbriquées améliorent l'encapsulation, la réutilisabilité et le contrôle de la portée. Cependant, les fonctions internes ne peuvent pas accéder directement aux variables locales des fonctions externes et le type de valeur de retour doit être cohérent avec la déclaration de la fonction externe. Les fonctions internes ne peuvent pas être auto-récursives.

Il existe plusieurs situations dans lesquelles cela indique en js Il existe plusieurs situations dans lesquelles cela indique en js May 06, 2024 pm 02:03 PM

En JavaScript, les types de pointage de this incluent : 1. Objet global ; 2. Appel de fonction ; 3. Appel de constructeur 4. Gestionnaire d'événements 5. Fonction de flèche (héritant de this). De plus, vous pouvez définir explicitement ce que cela désigne à l'aide des méthodes bind(), call() et apply().

La différence entre let et var en vue La différence entre let et var en vue May 08, 2024 pm 04:21 PM

Dans Vue, il existe une différence de portée lors de la déclaration de variables entre let et var : Scope : var a une portée globale et let a une portée au niveau du bloc. Portée au niveau du bloc : var ne crée pas de portée au niveau du bloc, let crée une portée au niveau du bloc. Redéclaration : var permet de redéclarer les variables dans la même portée, ce qui n'est pas le cas.

See all articles