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
angryTomavant
2019-11-29 14:02:022788parcourir

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();

[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();

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();

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


Chestnut 3

printName();     //printName is not a function
var printName = function(){
    console.log('波妞')
}
printName();       //波妞

est équivalent à

var printName;
printName();     //printName is not a function
printName = function(){
    console.log('波妞')
}
printName();       //波妞

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

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

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();

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;

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

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer