Maison > interface Web > js tutoriel > Comprendre les compétences javascript de Closures_Javascript

Comprendre les compétences javascript de Closures_Javascript

WBOY
Libérer: 2016-05-16 16:06:16
original
1118 Les gens l'ont consulté

1. Nous devons d’abord connaître la chaîne de portée variable

Il existe deux types de portées de variables : les variables globales et les variables locales. Les variables qui ne sont définies dans aucune fonction sont des variables globales et les variables définies dans une fonction sont des variables locales. Notez que vous devez utiliser le mot-clé var lors de la définition de variables à l'intérieur d'une fonction. Les variables sans le mot-clé var sont des variables globales.

Chaque morceau de code en JavaScript a une chaîne de portée associée. Cette chaîne de portée est une liste d'objets ou une liste chaînée qui définit les variables dans la « portée » de ce morceau de code. La portée du code de niveau supérieur se compose de variables globales ; la chaîne de portée qui n'inclut pas les fonctions imbriquées a deux objets : l'un est l'objet des paramètres de fonction définis et des variables locales, et l'autre est l'objet variable globale et le ; portée de la fonction imbriquée La chaîne comporte trois objets : paramètres de fonction et variables locales - paramètres de fonctions externes et variables locales - variables globales. Les fonctions peuvent accéder aux objets sur la chaîne de portée, de sorte que les fonctions peuvent accéder aux variables globales, mais pas l'inverse, c'est-à-dire que les variables locales au sein d'une fonction ne sont pas accessibles depuis l'extérieur de la fonction.

var a=1;
function wai(){
  alert(a);        
  var m=10;
  n=20;
}

wai();          //=> 1; 函数内部可以访问全局变量
alert(m);        //=> error; 外部访问函数局部变量报错  
alert(n);        //=> 20; 函数内部定义的变量未使用var关键字,所以是全局变量,外部可以访问
Copier après la connexion

2. Comment lire les variables locales en externe

Parfois, nous devons accéder aux variables locales au sein d'une fonction depuis l'extérieur. Dans ce cas, nous devons utiliser une solution de contournement. Nous utilisons les caractéristiques de la portée des variables JavaScript pour définir des sous-fonctions à l'intérieur de la fonction, et la sous-fonction peut accéder aux variables de la fonction parent

function wai(){
 var m=10;
  function nei(){
    alert(m); 
 }
  return nei;
}

var f = wai();
nei();              //=> error; nei()函数是一个局部变量,在外部不能访问
f();               //=> 10;
Copier après la connexion

3. Clôture

La fonction nei() dans le code précédent est une fermeture. Comme le montre ce qui précède, une fermeture est une fonction qui peut lire les variables locales à l'intérieur de la fonction. , il peut être considéré comme la fonction à l'intérieur et à l'extérieur de la fonction Ponts qui relient les extérieurs entre eux.

Les fermetures ont deux fonctions :

Tout d'abord, comme mentionné précédemment, vous pouvez lire les variables à l'intérieur de la fonction

Deuxièmement, ces variables locales peuvent être stockées en mémoire pour réaliser le partage de données variables

function wai(){
  var m=99;
  function nei(){
    alert(m);
    m++;
  }
  return nei;
}
      
var f= wai();
f();         //=> 99;
f();         //=> 100;
f();         //=> 101;
Copier après la connexion

Dans l'exemple ci-dessus, lorsque la fonction wai() est en cours d'exécution, la variable m est enregistrée dans la mémoire. La valeur de m peut être lue en exécutant f(), mais direct alert(m) ne le peut pas !

Nous pouvons également transmettre des paramètres à la fonction de fermeture. Comme le montre l'exemple suivant, une fonction anonyme est définie et une fonction de fermeture est renvoyée. La fonction ajoute les paramètres passés à la variable locale i dans la fonction anonyme, et Make. j'incrémente;

var wai=(function(){
  var i=0;
  return function(num){
    num+=i;
    alert(num);
    i++;
 }
})();
wai(1);//1
wai(2);//3
wai(3);//5
Copier après la connexion

Pour comprendre plus en profondeur les fermetures, regardons l'exemple suivant :

Maintenant, je veux définir une fonction qui renvoie un tableau, et chaque élément du tableau est une fonction, et chaque fonction affichera la valeur d'index correspondante

On pourrait écrire comme ça

function box(){
 var arr=[];
  for(i=0;i<5;i++){
    arr[i]=function(){return i;}
  }
 return arr;  
}
var a=box();
alert(a);        //=>包含五个函数体的数组
alert(a[0]());     //=> 5;
alert(a[1]());    //=> 5;
Copier après la connexion

Le code ci-dessus révèle que toutes les fenêtres contextuelles sont 5, et non 0,1,2,3,4 comme nous nous y attendions, car i est également une variable locale qui existe en mémoire lorsque nous exécutons a[0. ]() À ce moment-là, la valeur de i est déjà 5 et la valeur de i continue d'augmenter pendant tout le processus d'exécution de la fonction box().

Solution : Mise en place des fermetures

function box(){
var arr=[];
    for(var i=0;i<5;i++){

         arr[i]=(function(num){
           return function(){return num;}
         })(i);

     }
return arr;     
}

var arr=box();

for(var i=0;i<5;i++){

  alert(arr[i]());//0,1,2,3,4
}
Copier après la connexion

4. Choses à noter lors de l'utilisation des fermetures

1) Étant donné que les fermetures entraîneront le stockage des variables de la fonction en mémoire, ce qui consomme beaucoup de mémoire, les fermetures ne peuvent pas être abusées, sinon cela entraînerait des problèmes de performances sur la page Web et pourrait entraîner des fuites de mémoire dans C'est à dire. La solution consiste à supprimer toutes les variables locales inutilisées avant de quitter la fonction.

2) La fermeture modifiera la valeur de la variable à l'intérieur de la fonction parent en dehors de la fonction parent. Par conséquent, si vous utilisez la fonction parent comme objet, la fermeture comme méthode publique et les variables internes comme valeur privée, vous devez faire attention à ne pas modifier les valeurs des variables de la fonction parent.

5. Voici quelques questions sur les fermetures

Si vous pouvez comprendre les résultats du code suivant, vous devez comprendre le mécanisme de fonctionnement des fermetures.

Code Js

var name = "The Window"; 
var object = { 
  name : "My Object", 
  getNameFunc : function(){ 
    return function(){ 
      return this.name;       //=>嵌套函数的this为全局变量或undefined,不会继承父函数的this
    }; 
  } 
}; 
alert(object.getNameFunc()()); //The Window
Copier après la connexion

La raison pour laquelle la sortie ci-dessus est "La fenêtre" est que ceci dans la fonction imbriquée n'hérite pas de la fonction parent this, et sa valeur est une variable globale ou non définie (sous ECMAScript5), donc ce qui est renvoyé est le nom variable de l'objet global. Si vous souhaitez qu'il renvoie l'attribut name de l'objet, le code est le suivant :

var name = "The Window"; 
   var object = { 
    name : "My Object", 
    getNameFunc : function(){ 
      var cur=this;
      return function(){ 
        return cur.name;
      }; 
    } 
  }; 
  alert(object.getNameFunc()()); //=》My Object
Copier après la connexion

Le code ci-dessus attribue celui de l'objet fonction parent à la variable cur, et sa fonction imbriquée peut accéder à ses propriétés via la variable cur

-------------------------------------------------------------- --- ----------------------------------------------- --- -----
Exemple de fermeture JavaScript

function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
} 
}
innerFun();  //=>error
Copier après la connexion

Le code ci-dessus est erroné. La portée de innerFun() est à l'intérieur de externalFun(), et il est faux de l'appeler en dehors de externalFun().

est remplacé par ce qui suit, ce qui est une fermeture :

Code Js

function outerFun()
{
   var a=0;
  function innerFun()
  {
    a++;
    alert(a);
  }
  return innerFun; //注意这里
}
var obj=outerFun();
obj(); //结果为1
obj(); //结果为2
var obj2=outerFun();
obj2(); //结果为1
obj2(); //结果为2
Copier après la connexion

什么是闭包:

当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.

--------------------------------------------------------------------------------------------------------

再来看一个例子

Js代码

function outerFun()
{
   var a =0;
   alert(a); 
}
var a=4;
outerFun();   //=> 0
alert(a);      //=> 4
Copier après la connexion

结果是 0,4 . 因为在函数内部使用了var关键字 维护a的作用域在outFun()内部.

再看下面的代码:

Js代码

function outerFun()
{
//没有var 
a =0;
alert(a); 
}
var a=4;
outerFun();    //=> 0
alert(a);      //=> 0
Copier après la connexion

结果为 0,0 真是奇怪,为什么呢?

作用域链是描述一种路径的术语,沿着该路径可以确定变量的值 .当执行a=0时,因为没有使用var关键字,因此赋值操作会沿着作用域链到var a=4; 并改变其值.

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