Maison > interface Web > js tutoriel > Explication détaillée de la portée et de la fermeture de js

Explication détaillée de la portée et de la fermeture de js

angryTom
Libérer: 2019-11-29 14:03:17
avant
2810 Les gens l'ont consulté

Explication détaillée de la portée et de la fermeture de js

Portée

Il existe deux types de portée dans JS : portée globale | portée locale

Chestnut 1

console.log(name);      //undefined
var name = '波妞';
var like = '宗介'
console.log(name);      //波妞
function fun(){
    console.log(name);  //波妞
    console.log(eat)    //ReferenceError: eat is not defined
    (function(){
        console.log(like)   //宗介
        var eat = '肉'
    })()
}
fun();
Copier après la connexion

[Recommandations de cours associées : Tutoriel vidéo JavaScript]

1 Le nom est défini globalement et est accessible globalement, donc (2) L'impression peut être imprimé correctement ;

2. Dans la fonction fun, si l'attribut name n'est pas défini, il sera trouvé dans sa portée parent, donc (3) peut également être imprimé correctement.

3. L'environnement interne peut accéder à tous les environnements externes via la chaîne de portée, mais l'environnement externe ne peut accéder à aucune variable et fonction de l'environnement interne. Semblable à la Transparence unidirectionnelle, il s'agit d'une chaîne de portée, donc (4) ne fonctionne pas mais (5) oui.

Ensuite, la question se pose de savoir pourquoi la première impression est "non définie" au lieu de "ReferenceError : le nom n'est pas défini". Le principe est simplement que la Promotion variable

Promotion variable : Lorsque JS analyse le code, il avance toutes les déclarations au début de la portée


Chestnut 2

console.log(name);      //undefined
var name = '波妞';
console.log(name);      //波妞
function fun(){
    console.log(name)   //undefined
    console.log(like)   //undefined
    var name = '大西瓜';
    var like = '宗介'
}
fun();
Copier après la connexion

est équivalent à

var name;
console.log(name);      //undefined
name = '波妞';
console.log(name);      //波妞
function fun(){
    var name;
    var like;
    console.log(name)   //undefined
    console.log(like)   //undefined
    name = '大西瓜';
    like = '宗介'
    console.log(name)   //大西瓜
    console.log(like)   //宗介
}
fun();
Copier après la connexion

Remarque : est avancé à la portée actuelle L'avant


Chestnut 3

printName();     //printName is not a function
var printName = function(){
    console.log('波妞')
}
printName();       //波妞
Copier après la connexion

est équivalent à

var printName;
printName();     //printName is not a function
printName = function(){
    console.log('波妞')
}
printName();       //波妞
Copier après la connexion

De cette façon, il est plus facile de comprendre l'expression de la fonction. est dans Lorsqu'il est déclaré, ce n'est qu'une variable


Chestnut 4

{
    var name = '波妞';
}
console.log(name)   //波妞

(function(){
    var name = '波妞';
})()
console.log(name)   //ReferenceError: name is not defined

{
    let name = '波妞';
}
console.log(name)   //ReferenceError: name is not defined
Copier après la connexion

Comme le montre le châtaigne ci-dessus, les variables déclarées par var dans JS ne peuvent pas être considéré à la hâte La portée de est la portée de début et de fin des accolades ES5 n'a pas de portée au niveau du bloc, mais est essentiellement une portée de fonction Ce n'est qu'après l'introduction des définitions let et const dans ES6 qu'il y a eu un bloc. portée au niveau.


Chestnut 5

function p1() { 
    console.log(1);
}
function p2() { 
    console.log(2);
}
(function () { 
    if (false) {
        function p1() {
            console.log(3);
        }
    }else{
        function p2(){
            console.log(4)
        }
    }
    p2();
    p1()
})();       
//4
//TypeError: print is not a function
Copier après la connexion

C'est un châtaigne très classique, la déclaration est à l'avance, mais parce que la condition de jugement est non, la fonction corps ne l'est pas exécuté. Ainsi, "TypeError : l'impression n'est pas une fonction" apparaîtra. Il en va de même pour while, switch et for

closure

La fonction et la référence à son état, c'est-à-dire l'environnement lexical, constituent ensemble une fermeture. ). Autrement dit, les fermetures vous permettent d'accéder à la portée de la fonction externe à partir de la fonction interne. En JavaScript, les fonctions génèrent des fermetures à chaque fois qu'elles sont créées.

La définition ci-dessus vient de MDN. En termes simples, une fermeture fait référence à une fonction qui a accès à des variables dans le cadre d'une autre fonction.


● La clé de la fermeture est que son objet variable doit être détruit après l'appel de la fonction externe, mais l'existence de la fermeture nous permet toujours d'accéder à l'objet variable de la fonction externe. ,

//举个例子
function makeFunc() {
    var name = "波妞";
    function displayName() {
        console.log(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();
Copier après la connexion

Fonctions dans les fermetures de formulaires JavaScript. Une fermeture est composée d'une fonction et de l'environnement lexical qui crée la fonction. Cet environnement contient toutes les variables locales accessibles lors de la création de cette fermeture

Dans l'exemple, myFunc est une référence à l'instance de la fonction displayName créée lors de l'exécution de makeFunc, et l'instance displayName peut toujours accéder ses variables lexicales dans la portée peuvent accéder au nom. Ainsi, lorsque myFunc est appelé, le nom est toujours accessible et sa valeur « Ponyo » est transmise à console.log. La manière la plus courante de créer une fermeture est de créer une autre fonction à l'intérieur d'une fonction


● Habituellement, la portée d'une fonction et toutes ses variables se termineront à la fin la fin de l'exécution de la fonction a ensuite été détruite. Cependant, après avoir créé une fermeture, la portée de la fonction sera enregistrée jusqu'à ce que la fermeture n'existe plus

//例二
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

//释放对闭包的引用
add5 = null;
add10 = null;
Copier après la connexion

Essentiellement, makeAdder est une fabrique de fonctions - il crée la fonction A qui ajoute la somme d'un valeur spécifiée et ses arguments. Dans l'exemple ci-dessus, nous avons utilisé la fabrique de fonctions pour créer deux nouvelles fonctions : une qui additionne ses arguments plus 5 et une autre qui additionne 10 .

add5 et add10 sont tous deux des fermetures. Ils partagent la même définition de fonction, mais stockent des environnements lexicaux différents. Dans le contexte de add5, x vaut 5. Et dans add10, x vaut 10.

La chaîne de portée d'une fermeture contient sa propre portée, ainsi que la portée de sa fonction contenant et la portée globale.


● La fermeture ne peut obtenir que la dernière valeur de n'importe quelle variable dans la fonction contenant

//栗子1
function arrFun1(){
    var arr = [];
    for(var i = 0 ; i < 10 ; i++){
        arr[i] = function(){
            return i
        }
    }
    return arr
}
console.log(arrFun1()[9]());     //10
console.log(arrFun1()[1]());     //10

//栗子2
function arrFun2(){
    var arr = [];
    for(var i = 0 ; i < 10 ; i++){
        arr[i] = function(num){
            return function(){
                return num
            };
        }(i)
    }
    return arr
}
console.log(arrFun2()[9]());     //9
console.log(arrFun2()[1]());     //1
Copier après la connexion

Dans l'exemple 1, le tableau arr contient 10 Chaque La fonction anonyme peut accéder à la variable externe i. Après l'exécution de arrFun1, sa portée est détruite, mais ses variables existent toujours en mémoire et sont accessibles aux fonctions anonymes dans la boucle. Dans ce cas, i vaut 10 ; >Dans Chestnut 2, il y a une fonction anonyme dans le tableau arr, et il y a des fonctions anonymes dans la fonction anonyme. Le num auquel accède la fonction anonyme la plus interne est enregistré dans la mémoire par la fonction anonyme de niveau supérieur, il peut donc être. accédé à la valeur de i à chaque fois.

Cet article provient de la rubrique tutoriel js, bienvenue pour apprendre !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:cnblogs.com
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal