Maison  >  Article  >  interface Web  >  Notions de base de JavaScript (6) Expression de fonction Compétences Closure_Javascript

Notions de base de JavaScript (6) Expression de fonction Compétences Closure_Javascript

WBOY
WBOYoriginal
2016-05-16 15:26:22928parcourir

En fait, la principale raison pour laquelle js prend en charge les fermetures de fonctions est que js a besoin de fonctions pour pouvoir sauvegarder des données. Les données enregistrées ici sont que seules les valeurs des variables de la fonction seront enregistrées une fois la fonction terminée. Quant à savoir pourquoi js doit pouvoir sauvegarder des données dans une fonction, c'est que js est un langage fonctionnel. La sauvegarde des données dans les fonctions est une caractéristique des langages fonctionnels.

Revoyez les trois méthodes de définition des fonctions présentées précédemment

functosu(numnumreturnunum//Définition de la syntaxe de déclaration de fonction
vasufunction(numnum)returnunum}//Définition de l'expression de fonction
vasuneFunction("num""num""returnunum")//Constructeur de fonction

Avant d'analyser les fermetures, examinons d'abord les erreurs courantes dans la définition et l'appel des fonctions.

Exemple 1 :

sayHi(); //错误:函数还不存在
var sayHi = function () {
  alert("test");
};

Exemple 2 :

if (true) {
  function sayHi() {
    alert("1");
  }
} else {
  function sayHi() {
    alert("2");
  }
}
sayHi();//打印结果并不是我们想要的

Exemple 3 :

var fun1 = function fun2() {
  alert("test");
}
fun2();//错误:函数还不存在

Dans l'exemple 1, nous ne pouvons pas appeler la fonction avant de la définir en utilisant la syntaxe déclarative de fonction. Solution :

1. Si vous utilisez une expression de fonction pour définir une fonction, elle doit être appelée une fois l'expression définie.

var sayHi = function () {
  alert("test");
};
sayHi()

2. Utilisez les déclarations de fonctions. (Ici, le moteur du navigateur fera la promotion des déclarations de fonction et lira la déclaration de fonction avant que tout le code ne soit exécuté)

sayHi(); 
function sayHi () {
  alert("test");
};

Dans l'exemple 2, notre résultat attendu devrait être d'imprimer 1, mais le résultat réel est d'imprimer 2.

if (true) {
  function sayHi() {
   alert("1");
  }
  } else {
  function sayHi() {
   alert("2");
  }
}
sayHi();//打印结果并不是我们想要的

Pourquoi cela se produit-il ? En raison de la promotion de la déclaration de fonction, le navigateur ne jugera pas la condition if lors de la pré-analyse et écrasera directement la première lors de l'analyse de la deuxième définition de fonction.

Solution :

var sayHi;
if (true) {
  sayHi = function () {
   alert("1");
  }
  } else {
  sayHi = function () {
   alert("2");
  }
}
sayHi();

Dans l'exemple 3, nous avons constaté que nous ne pouvons utiliser que fun1() pour appeler, mais pas fun2().

D’après ma propre compréhension, je ne connais pas la vraie raison. Aucune information trouvée.

Parce que 1 : function fun3() { }; est équivalent à var fun3 = function fun3() { };

Vous ne pouvez donc utiliser que fun1() pour appeler, mais pas fun2().

En fait, j'ai encore des questions ici ? Si quelqu'un le sait, faites-le-moi savoir.

Puisque fun2 ne peut pas être appelé de l'extérieur, pourquoi peut-il être appelé depuis l'intérieur de la fonction ? Bien que je n'arrive toujours pas à m'amuser1 dans le débogueur.

D'accord, échauffeons-nous avec les trois questions ci-dessus. Continuons avec le sujet d’aujourd’hui des « fermetures ».

1. Qu'est-ce que la fermeture ?

Définition : C'est une fonction qui a accès à des variables dans le cadre d'une autre fonction

Commençons par un exemple de fonction :

Exemple 1 :

function fun() {
  var a = "张三";
}
fun();//在我们执行完后,变量a就被标记为销毁了
Exemple 2 :

function fun() {
  var a = "张三";
  return function () {
    alert("test");
  }
}
var f = fun();//同样,在我们执行完后,变量a就被标记为销毁了
Exemple 3 :

function fun() {
  var a = "张三";
  return function () {
    alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】
//这就是闭包,当函数A 返回的函数B 里面使用到了函数A的变量,那么函数B就使用了闭包。
示例:
function fun() {
  var a = "张三";
  return function () {
   alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】
De toute évidence, une mauvaise utilisation des fermetures augmentera l’utilisation de la mémoire. Essayez donc de ne pas utiliser de fermetures, sauf circonstances particulières. Si utilisé, pensez à définir manuellement une référence nulle afin que la mémoire puisse être recyclée f = null ;

Illustration : (Les étudiants qui ne comprennent pas la chaîne de portée, veuillez d'abord lire l'article précédent Portée et chaîne de portée)

2. Qu'est-ce qu'une fonction anonyme ? (J'explique juste le concept)

Par exemple : (c'est-à-dire une fonction sans nom)

À propos du phénomène étrange lorsque la valeur de retour de la fonction dans l'objet est une fonction anonyme

Avant d’expliquer, veuillez d’abord vous vider la tête et ne soyez pas plus confus pendant que vous lisez. Si vous êtes confus, ignorez simplement ce qui suit.

var name1 = "张三";
var obj = {
  name1: "李四",      
  fun2: function () {
    alert(this.name1);
  },
  fun3: function () {
    return function () {
      alert(this.name1);
    }
  }
}
obj.fun2();//Le résultat d'impression "李思" est comme prévu.
obj.fun3()();//Comme ce qui est renvoyé ici est une fonction, nous devons ajouter une paire de () pour l'appeler. Le résultat imprimé est "Zhang San", ce qui est inattendu.

//C’est vraiment déroutant. Qu’est-ce que cela signifie par rapport à la situation globale ?
Nous avons dit auparavant que "quel que soit l'objet qui clique sur la méthode, c'est l'objet", alors notre obj.fun3()() imprime "Zhang San", ce qui signifie que cela exécute la portée globale.

Nous pouvons comprendre pourquoi en regardant l'exemple ci-dessous.

Décomposons obj.fun3()(). Tout d'abord, obj.fun3() renvoie une fonction anonyme dans la portée de la fenêtre, puis l'appelle pour pointer vers la fenêtre. (J’ai l’impression que l’explication est un peu forcée, et je ne sais pas si c’est juste ou pas. C’est comme ça que je la comprends pour l’instant)

Cause de la formation de fermeture : problème de libération de mémoire

Généralement, lorsque la fonction est exécutée, l'objet actif local sera détruit et seule la portée globale est enregistrée en mémoire, mais la situation des fermetures est différente.

L'objet actif de la fermeture sera toujours enregistré dans la mémoire, donc dans l'exemple ci-dessus, après le retour de l'appel de fonction, la variable i appartient à l'objet actif, ce qui signifie que sa zone de pile n'a pas été libérée, mais vous appelez c() Lorsque la chaîne de portée enregistrée par la variable i passe de b()->a()-> globalement, elle recherche la déclaration de portée var i, puis trouve var i=1 et ensuite i; ; le résultat dans la fermeture, et enfin La valeur de sortie est 2 ;

Ce qui précède est la fermeture de l'expression de fonction dans JavaScript Basics Part 6 que l'éditeur a partagée avec vous. J'espère qu'elle vous plaira.

Déclaration:
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