Maison interface Web js tutoriel Vous amène à mieux comprendre les fermetures js (détails)

Vous amène à mieux comprendre les fermetures js (détails)

Oct 18, 2018 pm 01:39 PM
javascript

Le contenu de cet article est de vous aider à mieux comprendre les fermetures js (en détail). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Traducteur : On a tellement parlé des fermetures que même si je ne comprends pas les fermetures, je suis gêné de dire que je connais JS. Mais quand j'ai lu cet article, mes yeux se sont illuminés et. cela m'a aussi fait réfléchir aux fermetures. J'ai une nouvelle compréhension des packages, et cela implique une certaine connaissance des classes et des chaînes de prototypes. Il s'agit d'un article de 2012. Il est un peu tôt et le contenu est légèrement basique, mais il est très. clair. J'espère que cela pourra apporter une nouvelle compréhension aux lecteurs.

La fermeture est une fonctionnalité quelque peu complexe et mal comprise du langage JavaScript. En termes simples, une fermeture est un objet qui contient une méthode (fonction) et une référence à l'environnement lors de la création de la méthode. Afin de bien comprendre les fermetures, nous devons également comprendre deux fonctionnalités de js, l'une est la fonction de première classe et l'autre est la fonction interne.

Fonctions de première classe

En js, une méthode est un citoyen de première classe car elle peut être facilement convertie en d'autres types de données. Par exemple, une méthode de premier niveau peut être construite à la volée et affectée à une variable. Il peut également être transmis à d’autres méthodes ou renvoyé via d’autres méthodes. En plus de répondre à ces critères, les méthodes ont également leurs propres propriétés et méthodes.
A travers l'exemple suivant, jetons un œil aux capacités de la méthode de premier niveau.

var foo = function() {
  alert("Hello World!");
};

var bar = function(arg) {
  return arg;
};

bar(foo)();
Copier après la connexion
Note du traducteur : en omettant l'explication textuelle du code dans le texte original, ce qui se reflète ici est que la méthode de premier niveau peut renvoyer des paramètres, les paramètres peuvent être une autre fonction de premier niveau et le résultat renvoyé peut également être appelé.

Méthodes internes/Fonctions internes

Les méthodes internes ou méthodes imbriquées font référence à des méthodes définies dans d'autres méthodes. Chaque fois que la méthode externe est invoquée, l'instance de la méthode interne est créée. L'exemple suivant reflète l'utilisation de méthodes internes. La méthode add est une méthode externe et doAdd est une méthode interne.

function add(value1, value2) {
  function doAdd(operand1, operand2) {
    return operand1 + operand2;
  }

  return doAdd(value1, value2);
}

var foo = add(1, 2);
// foo equals 3
Copier après la connexion

Dans cet exemple, une caractéristique importante est que la méthode interne obtient la portée de la méthode externe, ce qui signifie que la méthode interne peut utiliser les variables, paramètres, etc. Dans l'exemple, les paramètres value1 et value2 de add() sont passés aux paramètres operand1 et operand2 de doAdd(). Cependant, cela n'est pas nécessaire car doAdd peut obtenir directement value1 et value2. On peut donc aussi écrire l'exemple ci-dessus comme ceci :

function add(value1, value2) {
  function doAdd() {
    return value1 + value2;
  }

  return doAdd();
}

var foo = add(1, 2);
// foo equals 3
Copier après la connexion

Création de fermetures/Création de fermetures

La méthode interne obtient la portée de la méthode externe, formant un fermeture. Un scénario typique est que la fonction externe renvoie sa méthode interne, qui conserve une référence à l'environnement externe et enregistre toutes les variables dans la portée.
L'exemple suivant montre comment créer et utiliser des fermetures.

function add(value1) {
  return function doAdd(value2) {
    return value1 + value2;
  };
}

var increment = add(1);
var foo = increment(2);
// foo equals 3
Copier après la connexion

Explication :

  • add renvoie la méthode interne doAdd, doAdd appelle les paramètres de add et la fermeture est créée.

  • value1 est une variable locale de la méthode add, qui est une variable non locale pour doAdd (une variable non locale signifie que la variable n'est ni dans le corps de la fonction lui-même ni dans le monde global), et value2 est une variable locale de doAdd .

  • Lorsque add(1) est appelé, une fermeture est créée et stockée par incrément. Dans l'environnement de référence de la fermeture, la valeur1 est liée à 1 et la limite 1 est équivalente à. "blocage" dans cette fonction, qui est aussi à l'origine du nom "fermeture".

  • Lorsque l'incrément(2) est appelé, la fonction de fermeture est entrée, ce qui signifie que la valeur comptable doAdd1 est 1 est appelée, donc la fermeture peut essentiellement être considérée comme la fonction suivante :

function increment(value2) {
  return 1 + value2;
}
Copier après la connexion

Quand utiliser les fermetures ?

Les fermetures peuvent remplir de nombreuses fonctions. Par exemple, liez la fonction de rappel aux paramètres spécifiés. Parlons de deux scénarios qui facilitent votre vie et votre développement.

  1. Travailler avec des minuteries

Les fermetures sont très utiles en combinaison avec setTimeout et setInterval. Les fermetures vous permettent de transmettre des paramètres spécifiés à la fonction de rappel, comme ce qui suit Par exemple, insérez une chaîne dans le dom spécifié chaque seconde.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Closures</title>
  <meta charset="UTF-8" />
  <script>
    window.addEventListener("load", function() {
      window.setInterval(showMessage, 1000, "some message<br />");
    });

    function showMessage(message) {
      document.getElementById("message").innerHTML += message;
    }
  </script>
</head>
<body>
  <span id="message"></span>
</body>
</html>
Copier après la connexion

Malheureusement, IE ne prend pas en charge la transmission de paramètres au rappel setInterval. La page dans IE n'affichera pas "un message" mais "indéfini" (aucune valeur n'est transmise à showMessage() pour résoudre). ce problème Question, nous pouvons lier la valeur attendue à la fonction de rappel via la fermeture. Nous pouvons réécrire le code ci-dessus :

window.addEventListener("load", function() {
  var showMessage = getClosure("some message<br />");

  window.setInterval(showMessage, 1000);
});

function getClosure(message) {
  function showMessage() {
    document.getElementById("message").innerHTML += message;
  }

  return showMessage;
}
Copier après la connexion

2. Simuler les propriétés privées
La plupart des langages de programmation orientés objet sont pris en charge. la confidentialité des propriétés des objets, cependant, js n'est pas un pur langage orienté objet, il n'y a donc pas de concept de propriétés privées. Cependant, nous pouvons simuler des propriétés privées via des fermetures. Rappelons qu'une fermeture contient une référence à l'environnement dans lequel elle a été créée. Cette référence n'est plus dans la portée actuelle, cette référence n'est donc accessible qu'au sein de la fermeture. Il s'agit essentiellement d'une propriété privée.
Regardez l'exemple suivant (Traducteur : omettre la description textuelle du code) :

function Person(name) {
  this._name = name;

  this.getName = function() {
    return this._name;
  };
}
Copier après la connexion

Il y a un problème sérieux ici, car js ne prend pas en charge les attributs privés, nous ne pouvons donc pas empêcher les autres de modifier Dans le champ Nom de l'instance, par exemple, nous créons une instance de Personne appelée Colin, puis changeons son nom en Tom.

var person = new Person("Colin");

person._name = "Tom";
// person.getName() now returns "Tom"
Copier après la connexion

没有人愿意不经同意就被别人改名字,为了阻止这种情况的发生,通过闭包让_name字段变成私有。看如下代码,注意这里的_name是Person构造器的本地变量,而不是对象的属性,闭包形成了,因为外层方法Person对外暴露了一个内部方法getName。

function Person(name) {
  var _name = name;// 注:区别在这里

  this.getName = function() {
    return _name;
  };
}
Copier après la connexion

现在,当getName被调用,能够保证返回的是最初传入类构造器的值。我们依然可以为对象添加新的_name属性,但这并不影响闭包getName最初绑定的值,下面的代码证明,_name字段,事实私有。

var person = new Person("Colin");

person._name = "Tom";
// person._name is "Tom" but person.getName() returns "Colin"
Copier après la connexion

什么时候不要用闭包?

正确理解闭包如何工作何时使用非常重要,而理解什么时候不应该用它也同样重要。过度使用闭包会导致脚本执行变慢并消耗额外内存。由于闭包太容易创建了,所以很容易发生你都不知道怎么回事,就已经创建了闭包的情况。本节我们说几种场景要注意避免闭包的产生。
1.循环中
循环中创建出闭包会导致结果异常。下例中,页面上有三个按钮,分别点击弹出不同的话术。然而实际运行,所有的按钮都弹出button4的话术,这是因为,当按钮被点击时,循环已经执行完毕,而循环中的变量i也已经变成了最终值4.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Closures</title>
  <meta charset="UTF-8" />
  <script>
    window.addEventListener("load", function() {
      for (var i = 1; i < 4; i++) {
        var button = document.getElementById("button" + i);

        button.addEventListener("click", function() {
          alert("Clicked button " + i);
        });
      }
    });
  </script>
</head>
<body>
  <input type="button" id="button1" value="One" />
  <input type="button" id="button2" value="Two" />
  <input type="button" id="button3" value="Three" />
</body>
</html>
Copier après la connexion

去解决这个问题,必须在循环中去掉闭包(译者:这里的闭包指的是click事件回调函数绑定了外层引用i),我们可以通过调用一个引用新环境的函数来解决。下面的代码中,循环中的变量传递给getHandler函数,getHandler返回一个闭包(译者:这个闭包指的是getHandler返回的内部方法绑定传入的i参数),独立于原来的for循环。

function getHandler(i) {
  return function handler() {
    alert("Clicked button " + i);
  };
}

window.addEventListener("load", function() {
  for (var i = 1; i < 4; i++) {
    var button = document.getElementById("button" + i);

    button.addEventListener("click", getHandler(i));
  }
});
Copier après la connexion

2.构造函数里的非必要使用
类的构造函数里,也是经常会产生闭包的错误使用。我们已经知道如何通过闭包设置类的私有属性,而如果当一个方法不需要调用私有属性,则造成的闭包是浪费的。下面的例子中,Person类增加了sayHello方法,但是它没有使用私有属性。

function Person(name) {
  var _name = name;

  this.getName = function() {
    return _name;
  };

  this.sayHello = function() {
    alert("Hello!");
  };
}
Copier après la connexion

每当Person被实例化,创建sayHello都要消耗时间,想象一下有大量的Person被实例化。更好的实践是将sayHello放入Person的原型链里(prototype),原型链里的方法,会被所有的实例化对象共享,因此节省了为每个实例化对象去创建一个闭包(译者:指sayHello),所以我们有必要做如下修改:

function Person(name) {
  var _name = name;

  this.getName = function() {
    return _name;
  };
}

Person.prototype.sayHello = function() {
  alert("Hello!");
};
Copier après la connexion

需要记得一些事情

闭包包含了一个方法,以及创建它的代码环境引用

闭包会在外部函数包含内部函数的情况下形成

闭包可以轻松的帮助回调函数传入参数

类的私有属性可以通过闭包模拟

类的构造器中使用闭包不是一个好主意,将它们放到原型链中

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 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

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

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)

Comment mettre en œuvre un système de reconnaissance vocale en ligne à l'aide de WebSocket et JavaScript Comment mettre en œuvre un système de reconnaissance vocale en ligne à l'aide de WebSocket et JavaScript Dec 17, 2023 pm 02:54 PM

Comment utiliser WebSocket et JavaScript pour mettre en œuvre un système de reconnaissance vocale en ligne Introduction : Avec le développement continu de la technologie, la technologie de reconnaissance vocale est devenue une partie importante du domaine de l'intelligence artificielle. Le système de reconnaissance vocale en ligne basé sur WebSocket et JavaScript présente les caractéristiques d'une faible latence, d'un temps réel et d'une multiplateforme, et est devenu une solution largement utilisée. Cet article explique comment utiliser WebSocket et JavaScript pour implémenter un système de reconnaissance vocale en ligne.

WebSocket et JavaScript : technologies clés pour mettre en œuvre des systèmes de surveillance en temps réel WebSocket et JavaScript : technologies clés pour mettre en œuvre des systèmes de surveillance en temps réel Dec 17, 2023 pm 05:30 PM

WebSocket et JavaScript : technologies clés pour réaliser des systèmes de surveillance en temps réel Introduction : Avec le développement rapide de la technologie Internet, les systèmes de surveillance en temps réel ont été largement utilisés dans divers domaines. L'une des technologies clés pour réaliser une surveillance en temps réel est la combinaison de WebSocket et de JavaScript. Cet article présentera l'application de WebSocket et JavaScript dans les systèmes de surveillance en temps réel, donnera des exemples de code et expliquera leurs principes de mise en œuvre en détail. 1. Technologie WebSocket

Comment utiliser JavaScript et WebSocket pour mettre en œuvre un système de commande en ligne en temps réel Comment utiliser JavaScript et WebSocket pour mettre en œuvre un système de commande en ligne en temps réel Dec 17, 2023 pm 12:09 PM

Introduction à l'utilisation de JavaScript et de WebSocket pour mettre en œuvre un système de commande en ligne en temps réel : avec la popularité d'Internet et les progrès de la technologie, de plus en plus de restaurants ont commencé à proposer des services de commande en ligne. Afin de mettre en œuvre un système de commande en ligne en temps réel, nous pouvons utiliser les technologies JavaScript et WebSocket. WebSocket est un protocole de communication full-duplex basé sur le protocole TCP, qui peut réaliser une communication bidirectionnelle en temps réel entre le client et le serveur. Dans le système de commande en ligne en temps réel, lorsque l'utilisateur sélectionne des plats et passe une commande

Comment mettre en œuvre un système de réservation en ligne à l'aide de WebSocket et JavaScript Comment mettre en œuvre un système de réservation en ligne à l'aide de WebSocket et JavaScript Dec 17, 2023 am 09:39 AM

Comment utiliser WebSocket et JavaScript pour mettre en œuvre un système de réservation en ligne. À l'ère numérique d'aujourd'hui, de plus en plus d'entreprises et de services doivent fournir des fonctions de réservation en ligne. Il est crucial de mettre en place un système de réservation en ligne efficace et en temps réel. Cet article explique comment utiliser WebSocket et JavaScript pour implémenter un système de réservation en ligne et fournit des exemples de code spécifiques. 1. Qu'est-ce que WebSocket ? WebSocket est une méthode full-duplex sur une seule connexion TCP.

JavaScript et WebSocket : créer un système efficace de prévisions météorologiques en temps réel JavaScript et WebSocket : créer un système efficace de prévisions météorologiques en temps réel Dec 17, 2023 pm 05:13 PM

JavaScript et WebSocket : Construire un système efficace de prévisions météorologiques en temps réel Introduction : Aujourd'hui, la précision des prévisions météorologiques revêt une grande importance pour la vie quotidienne et la prise de décision. À mesure que la technologie évolue, nous pouvons fournir des prévisions météorologiques plus précises et plus fiables en obtenant des données météorologiques en temps réel. Dans cet article, nous apprendrons comment utiliser la technologie JavaScript et WebSocket pour créer un système efficace de prévisions météorologiques en temps réel. Cet article démontrera le processus de mise en œuvre à travers des exemples de code spécifiques. Nous

Tutoriel JavaScript simple : Comment obtenir le code d'état HTTP Tutoriel JavaScript simple : Comment obtenir le code d'état HTTP Jan 05, 2024 pm 06:08 PM

Tutoriel JavaScript : Comment obtenir le code d'état HTTP, des exemples de code spécifiques sont requis Préface : Dans le développement Web, l'interaction des données avec le serveur est souvent impliquée. Lors de la communication avec le serveur, nous devons souvent obtenir le code d'état HTTP renvoyé pour déterminer si l'opération a réussi et effectuer le traitement correspondant en fonction de différents codes d'état. Cet article vous apprendra comment utiliser JavaScript pour obtenir des codes d'état HTTP et fournira quelques exemples de codes pratiques. Utilisation de XMLHttpRequest

Comment utiliser insertBefore en javascript Comment utiliser insertBefore en javascript Nov 24, 2023 am 11:56 AM

Utilisation : En JavaScript, la méthode insertBefore() est utilisée pour insérer un nouveau nœud dans l'arborescence DOM. Cette méthode nécessite deux paramètres : le nouveau nœud à insérer et le nœud de référence (c'est-à-dire le nœud où le nouveau nœud sera inséré).

JavaScript et WebSocket : créer un système de traitement d'images en temps réel efficace JavaScript et WebSocket : créer un système de traitement d'images en temps réel efficace Dec 17, 2023 am 08:41 AM

JavaScript est un langage de programmation largement utilisé dans le développement Web, tandis que WebSocket est un protocole réseau utilisé pour la communication en temps réel. En combinant les puissantes fonctions des deux, nous pouvons créer un système efficace de traitement d’images en temps réel. Cet article présentera comment implémenter ce système à l'aide de JavaScript et WebSocket, et fournira des exemples de code spécifiques. Tout d’abord, nous devons clarifier les exigences et les objectifs du système de traitement d’images en temps réel. Supposons que nous disposions d'un appareil photo capable de collecter des données d'image en temps réel.

See all articles