javascript - À quoi servent les fermetures dans le développement pratique?
PHPz
PHPz 2017-05-16 13:35:00
0
9
971

Après avoir regardé l'explication de la fonction des fermetures dans la vidéo, je ne comprends toujours pas. Par exemple, le code dans la capture d'écran peut être implémenté en ajoutant un paramètre passline à la fonction cmp.

Qui peut donner un meilleur exemple pour illustrer le rôle de la clôture ?

PHPz
PHPz

学习是最好的投资!

répondre à tous(9)
过去多啦不再A梦

Prolongez le cycle de vie des variables locales et encapsulez des variables privées

2. 延续局部变量的寿命
img 对象经常用于进行数据上报,如下所示:
var report = function( src ){
    var img = new Image();
    img.src = src;
};
report( 'http://xxx.com/getUserInfo' );
但是通过查询后台的记录我们得知,因为一些低版本浏览器的实现存在 bug,在这些浏览器
下使用 report 函数进行数据上报会丢失 30%左右的数据,也就是说, report 函数并不是每一次
都成功发起了 HTTP 请求。丢失数据的原因是 img 是 report 函数中的局部变量,当 report 函数的
调用结束后, img 局部变量随即被销毁,而此时或许还没来得及发出 HTTP 请求,所以此次请求
就会丢失掉。
现在我们把 img 变量用闭包封闭起来,便能解决请求丢失的问题:
var report = (function(){
    var imgs = [];
    return function( src ){
        var img = new Image();
        imgs.push( img );
        img.src = src;
    }
})();
伊谢尔伦

Enregistrer les variables. La plupart du temps, je l'utilise pour remplacer les variables globales afin d'éviter la pollution variable

.
巴扎黑

Problèmes résolus par les fermetures : Basé sur les JS词法作用域规则,其访问是一直向上查找作用域,直到全局作用域。而想直接访问某个作用域可通过闭包解决。

function foo(){
var a = 1;
function bar(){
    console.log(a);
}
return bar;
}
var baz = foo();
baz();

bar词法作用域可以访问foo内部作用域,foo执行后返回bar,最后赋值给baz,可以获取并访问foo内部作用域,只是标识符不同而已。
该代码就使用了闭包,可以说写JS代码处处可见闭包,使用闭包还有一个好处就是引用的作用域不会被垃圾回收处理,当然不合理的使用会耗内存

闭包用来增加变量(能访问某作用域,自然能加变量)或者延长其生命周期(作用域被引用,自然会延长)

for (var i = 0; i < 5; i++){
    setTimeout(function(){
    console.log(i)},i * 1000)
}    

for (var i = 0; i < 5; i++){
    (function (i) {
    setTimeout(function(){
    console.log(i)},i * 1000)
    })(i)    
}

第一个循环是声明了几个函数,共享全局i变量(变量和函数声明都提升了)。
第二个循环是定义了几个立即执行函数,又传递了i值,故每个irègles de portée lexicale
de JS, son accès consiste à rechercher la portée vers le haut jusqu'à la

portée globale

. Si vous souhaitez accéder directement à une certaine portée, vous pouvez utiliser des fermetures. rrreee La portée lexicale de bar peut accéder à la portée interne de foo Une fois foo exécuté, il renvoie bar. et enfin l'attribue à baz, peut obtenir et accéder à la portée interne de foo, mais l'identifiant est différent.

Ce code utilise des fermetures.On peut dire que les fermetures peuvent être vues partout lors de l'écriture du code JS. Un autre avantage de l'utilisation des fermetures est que la portée référencée ne sera pas récupérée, ce qui est bien sûr déraisonnable. Son utilisation consommera de la mémoire

. Les fermetures servent à

ajouter des variables 🎜 (si vous pouvez accéder à un certain scope, vous pouvez naturellement ajouter des variables) ou 🎜 prolonger son cycle de vie 🎜 (lorsque le scope est référencé, il sera naturellement étendu) 🎜 rrreee 🎜La première boucle déclare plusieurs fonctions et partage la variable globale i (les déclarations de variables et de fonctions sont promues). 🎜La deuxième boucle définit plusieurs fonctions d'exécution immédiate et transmet la valeur i, donc chaque valeur i a sa propre portée. 🎜C'est un meilleur exemple, fermeture + boucle, mais celui-ci est spécial, la fermeture accède à sa propre portée. 🎜 🎜🎜Bien sûr, le module qui incarne le mieux l'idée de fermeture est le module, qui renvoie une méthode, qui introduit effectivement une portée. 🎜🎜 🎜🎜 Fermeture : C'est un moyen d'obtenir et d'accéder à un certain périmètre, accessible de l'extérieur ou de l'intérieur de lui-même. 🎜🎜
Ty80

Les deux plus grandes fonctions

  1. Lire les variables internes de la fonction

  2. Toujours garder les valeurs des variables en mémoire

Je n'entrerai pas dans les détails du premier, mais regardez le second pour un exemple

function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000   

le résultat est en fait la fonction de fermeture f2. Il a été exécuté deux fois, la première fois, la valeur était de 999, la deuxième fois, la valeur était de 1 000. Cela prouve que la variable locale n dans la fonction f1 est toujours stockée en mémoire et n'est pas automatiquement effacée après l'appel de f1.
Pourquoi cela se produit-il ? La raison en est que f1 est la fonction parent de f2 et que f2 est affecté à une variable globale, ce qui fait que f2 est toujours en mémoire, et l'existence de f2 dépend de f1, donc f1 est toujours en mémoire et ne sera pas supprimé. une fois l'appel terminé, recyclé par le mécanisme de récupération de place (garbage collection).
Une autre chose à noter dans ce code est la ligne "nAdd=function(){n+=1}". Tout d'abord, le mot-clé var n'est pas utilisé avant nAdd, donc nAdd est une variable globale, pas une variable locale. Deuxièmement, la valeur de nAdd est une fonction anonyme, et cette fonction anonyme elle-même est également une fermeture, donc nAdd est équivalent à un setter, qui peut opérer sur des variables locales à l'intérieur de la fonction depuis l'extérieur de la fonction

  • Gérez les variables privées et les méthodes privées, et encapsulez les modifications apportées aux variables (état) dans un environnement sécurisé

  • Encapsulez le code dans un formulaire de fermeture et attendez qu'il soit utilisé le moment venu, par exemple en implémentant le currying et le dé-currying

  • À noter :

    • Étant donné que certaines ressources de la fermeture ne peuvent pas être automatiquement libérées, il est facile de provoquer des fuites de mémoire. La solution consiste à supprimer toutes les variables locales inutilisées avant de quitter la fonction.

    • 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 librement la valeur de la variable à l'intérieur de la fonction parent.

世界只因有你

Si je dis, set_passLine est en fait fonction de deux paramètres, pouvez-vous l'accepter ?

def set_passLine(passline)(val): # 虽然这不符合语法
    pass

Cette fonction somme

def set_passLine(passline,val):
    pass

sont fonctionnellement équivalents, mais le premier n'a pas besoin d'être appelé avec tous les paramètres à la fois.

De plus, la première façon d'écrire peut remplir la même fonction qu'une classe :

def set_passLine(passline):
    def cmp(val):
        pass
    def resetPassLine(newPassline):
        passline=newPassline
        pass
    return (cmp,resetPassLine)

Bien qu'il s'agisse d'implémentations différentes de la même fonctionnalité. Mais les gens trouvent de plus en plus que la programmation fonctionnelle est meilleure que les autres méthodes. Mieux signifie mieux et plus clair en termes de taille de code (mais les exigences pour les programmeurs sont de plus en plus élevées).

Donnez-moi un lien, mais je l'ai écrit en js : http://zonxin.github.io/post/...

P.S.
La programmation orientée objet consiste à considérer tous les « objets » comme des objets. La programmation consiste à utiliser des objets pour simuler le comportement des « objets », c'est-à-dire simuler le fonctionnement d'un certain « monde ».
La programmation fonctionnelle ne se soucie que de l'état initial de « l'objet » et de l'état final de « l'objet » après avoir traversé la fonction, sans se soucier du processus. La programmation consiste à s'occuper de la composition de ces fonctions.

滿天的星座

Je l'ai toujours compris de cette façon : protéger les variables internes et fonctionner via des API exposées.

var name="meimei"
function Private(){
    var name = "leilei";
    return {
        getName:function(){
            console.log(name)
        },
        setName:function(val){
            name = val;
        }
    }
}
var private = Private();
private.getName()//"leilei"
private.setName("xiaoming")
private.getName()//"xiaoming"
name//"meimei"
//通过暴漏API来操作内部变量。
jquery:
(function(){
...
    window.$=window.jquery=window.jQuery=...
})
//一个匿名自执行函数通过window暴漏jquery,内部变量不会受到其他全局变量的污染,只能通过$的API进行操作。

Ce qui précède est ma compréhension personnelle

Ty80

Évitez la pollution variable, mais si c'est en ES6, utilisez let et const pour résoudre ce problème

大家讲道理

Au niveau élémentaire
Je sais seulement que 1. Vous pouvez accéder aux variables locales
2 Elles peuvent toujours être enregistrées en mémoire

.

La fréquence d'utilisation ne doit donc pas être trop élevée, car cela pourrait provoquer des fuites de mémoire

PHPzhong

Répondez à quelque chose qui m'a impressionné 偏函数

function logger(logType){
    return console.log.bind(console, logType); 
}

var info = logger('[INFO]'); 
var error = logger('[ERROR]'); 

info('this is an info'); 
// => 
// [INFO] this is an info

error('this is an error'); 
// => 
// [ERROR] this is an error
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal