Abschlüsse – überall
In der Frontend-Programmierung ist die Verwendung von Abschlüssen sehr verbreitet. Wir verwenden Abschlüsse oft absichtlich oder unabsichtlich, direkt oder indirekt. Schließungen können die Datenübertragung flexibler machen (z. B. die Handhabung einiger Klickereignisse)
!function() { var localData = "localData here"; document.addEventListener('click', //处理点击事件时用到了外部局部变量,比如这里的localData function(){ console.log(localData); }); }();
Ein weiteres Beispiel ist das folgende Beispiel: (Ist es nicht sehr freundlich~~)
!function() { var localData = "localData here"; var url = "http://www.baidu.com/"; $.ajax({ url : url, success : function() { // do sth... console.log(localData); } }); }();
Schauen wir uns ein anderes Beispiel an. Diese Situation nennen wir normalerweise Schließung
function outer() { var localVal = 30; return function(){ return localVal; } } var func = outer(); func(); // 30
In diesem Beispiel wird äußere() aufgerufen, um die anonyme Funktion zurückzugeben Funktion() In dieser anonymen Funktion ist die lokale Auf die Variable localVal von Outer() kann zugegriffen werden. Nachdem der Aufruf von Outer() abgeschlossen ist, kann beim erneuten Aufruf von Func() immer noch auf die lokale Variable LocalVal von Outer() zugegriffen werden
Das Konzept des Abschlusses
Der Abschluss unterscheidet sich vom Allgemeinen. Eine Funktion, die es einer Funktion ermöglicht, weiterhin auf nicht-lokale Variablen zuzugreifen, wenn sie außerhalb des unmittelbaren lexikalischen Bereichs aufgerufen wird. --Wikipedia
Ein Abschluss ist eine Funktion, die die internen Variablen anderer Funktionen lesen kann. --Ruan Yifeng
Da in der Javascript-Sprache nur Unterfunktionen innerhalb der Funktion lokale Variablen lesen können, können Abschlüsse einfach als „innerhalb einer Funktion definierte Funktionen“ verstanden werden.
Im Wesentlichen ist der Abschluss also eine Brücke, die das Innere einer Funktion mit der Außenseite der Funktion verbindet
Der Zweck des Abschlusses
Dieser Teil ist aus diesem Blog reproduziert Beitrag
Verschlüsse können an vielen Stellen eingesetzt werden. Es hat zwei Hauptverwendungszwecke: Zum einen werden die Variablen innerhalb der Funktion gelesen, und zum anderen werden die Werte dieser Variablen im Speicher gehalten.
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
In diesem Code ist das Ergebnis tatsächlich die Abschlussfunktion f2. Es wurde zweimal ausgeführt, beim ersten Mal war der Wert 999, beim zweiten Mal war der Wert 1000. Dies beweist, dass die lokale Variable n in der Funktion f1 immer im Speicher gespeichert ist und nach dem Aufruf von f1 nicht automatisch gelöscht wird.
Warum passiert das? Der Grund dafür ist, dass f1 die übergeordnete Funktion von f2 ist und f2 einer globalen Variablen zugewiesen ist, wodurch f2 immer im Speicher bleibt und die Existenz von f2 von f1 abhängt, sodass f1 immer im Speicher ist und nicht gelöscht wird Nach Abschluss des Anrufs wird es vom Garbage-Collection-Mechanismus recycelt.
Eine weitere erwähnenswerte Sache in diesem Code ist die Zeile „nAdd=function(){n =1}“. Erstens wird das Schlüsselwort var nicht vor nAdd verwendet, daher ist nAdd eher eine globale Variable als lokale Variablen. Zweitens ist der Wert von nAdd eine anonyme Funktion, und die anonyme Funktion selbst ist auch ein Abschluss, sodass nAdd einem Setter entspricht, der lokale Variablen innerhalb der Funktion außerhalb der Funktion bearbeiten kann.
Closure-Encapsulation
(function() { var _userId = 23492; var _typeId = 'item'; var export = {}; function converter(userId) { return +userId; } export.getUserId = function() { return converter(_userId); } export.getTypeId = function() { return _typeId; } window.export = export; //通过此方式输出 }()); export.getUserId(); // 23492 export.getTypeId(); // item export._userId; // undefined export._typeId; // undefined export.converter; // undefined
Die Verwendung der Verschlusseigenschaften ermöglicht es uns, einige komplexe Funktionslogiken zu kapseln. In diesem Beispiel rufen Sie die Exportmethode (getUserId, getTypeId) für den indirekten Zugriff auf private Variablen in der Funktion, aber Sie können _userId nicht durch direkten Aufruf von export._userId erhalten. Dies ist auch eine häufig verwendete Funktion in Node~
Häufige Fehler: Schleifenschluss
Im folgenden Fall fügen wir 3 Divs mit den Werten aaa, bbb, ccc hinzu Klicken Sie auf aaa, um 1 auszugeben, klicken Sie auf bbb, um 2 auszugeben, und klicken Sie auf ccc, um 3 auszugeben. Klicken Sie daher auf aaa, bbb oder ccc Ausgabealarm(4)~~
document.body.innerHTML = "<div id=div1>aaa</div>" + "<div id=div2>bbb</div><div id=div3>ccc</div>"; for (var i = 1; i < 4; i++) { document.getElementById('div' + i). addEventListener('click', function() { alert(i); // all are 4! }); }
Um das zu erreichen, was wir wollen, klicken Sie auf aaa, um 1 auszugeben, und klicken Sie auf bbb, um Geben Sie 2 aus und klicken Sie auf ccc, um 3 auszugeben. Um die Abschlusstechnik zu verwenden, schließen Sie sie mit einer anonymen Funktion ein, die sofort während jeder Schleife ausgeführt wird. Auf diese Weise wird der Wert von Alert(i) von i in der Abschlussumgebung übernommen . Diese Aufgabe i aus jeder Schleife kann 1, 2, 3 ausgeben
Denkfragen
如果你能理解下面两段代码的运行结果,应该就算理解闭包的运行机制了。(来自阮老师)这题目总结得真秒~~
代码片段一。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());
代码片段二。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());