Das Beispiel in diesem Artikel beschreibt die Verwendung des Javascript-Abschlusses (Closure). Teilen Sie es als Referenz mit allen. Die Details lauten wie folgt:
Abschluss wird mit „Abschluss“ übersetzt, und ich finde, dass diese Sache zu akademisch verpackt ist. Lassen Sie uns dies kurz anhand von Büchern und Online-Ressourcen besprechen (bitte achten Sie auf unangemessenes Verständnis).
1. Was ist Schließung
Offizielle Antwort: Der sogenannte „Abschluss“ bezieht sich auf einen Ausdruck (normalerweise eine Funktion), der viele Variablen und eine an diese Variablen gebundene Umgebung hat, sodass diese Variablen auch Teil des Ausdrucks sind.
Wenn Sie nach dem Lesen der obigen Definition kein Experte sind, bin ich fest davon überzeugt, dass Sie wie ich wütend fragen werden: Ist das die menschliche Sprache?
Um Abschlüsse zu verstehen, ist Code am überzeugendsten. Hier ist der Code:
function funcTest() { var tmpNum=100; //私有变量 //在函数funcTest内定义另外的函数作为funcTest的方法函数 function innerFuncTest( { alert(tmpNum); //引用外层函数funcTest的临时变量tmpNum } return innerFuncTest; //返回内部函数 } //调用函数 var myFuncTest=funcTest(); myFuncTest();//弹出100
Im obigen Code wurden die Kommentare klar geschrieben. Jetzt können wir „Abschluss“ wie folgt verstehen: Definieren Sie eine andere Funktion im Funktionskörper als Methodenfunktion des Zielobjekts (im Beispiel definieren Sie eine andere Funktion innerFuncTest als Methodenfunktion von funcTest innerhalb der Funktion funcTest) und die Methodenfunktion Dieses Objekt ist das Gegenteil, um auf die temporären Variablen im äußeren Funktionskörper zu verweisen (Abschluss ist ein Mechanismus zum indirekten Verwalten von Variablenwerten. Im Beispiel bezieht sich die innere Funktion innerFuncTest auf die temporäre Variable tmpNum der äußeren Funktion funcTest. Es Dabei ist zu beachten, dass temporäre Variablen in die äußere Funktion alle deklarierten lokalen Variablen, Parameter und andere deklarierte interne Funktionen eingebunden werden können. Wenn eine dieser inneren Funktionen außerhalb der sie enthaltenden äußeren Funktion aufgerufen wird, wird ein Abschluss gebildet (im Beispiel ruft myFuncTest beim Aufrufen der Funktion tatsächlich die Funktion innerFuncTest auf, was bedeutet, dass eine innere Funktion von funcTest, innerFuncTest, außerhalb aufgerufen wird). funcTest wird ein Abschluss erstellt).
2. Zwei Beispiele für die Verwendung von Verschlüssen
Hier sind zwei Beispiele, weil Abschlüsse Probleme verursachen, und das andere verwendet Abschlüsse, um Parameter geschickt über den Umfang einer Funktion zu binden.
Die HTML-Markup-Fragmente, die sich auf diese beiden Beispiele beziehen, lauten wie folgt:
<a href="#" id="closureTest0">利用闭包的例子(1秒后会看到提示)</a><br /> <a href="#" id="closureTest1">由于闭包导致问题的例子1</a><br /> <a href="#" id="closureTest2">由于闭包导致问题的例子2</a><br /> <a href="#" id="closureTest3">由于闭包导致问题的例子3</a><br />
(1) Probleme durch Schließungen
Das obige HTML-Tag-Fragment enthält vier -Elemente. Den letzten drei müssen wir nun Ereignishandler zuweisen, damit sie ihre Reihenfolge auf der Seite melden, wenn der Benutzer beispielsweise klickt Beim Verlinken auf den 2. Link wird angezeigt: „Sie haben auf den 1. Link geklickt“. Schreiben Sie dazu die folgende Funktion, die Ereignishandler für die letzten drei Links hinzufügt:
function badClosureExample(){ for (var i = 1; i <4; i++) { var element = document.getElementById('closureTest' + i); element .onclick = function(){ alert('您单击的是第' + i + '个链接'); } } }
Rufen Sie dann diese Funktion auf, nachdem die Seite geladen wurde (andernfalls wird möglicherweise ein Fehler gemeldet):
window.onload = function(){ badClosureExample(); }
Sehen Sie sich die laufenden Ergebnisse an. Welche Informationen werden im Warnfeld angezeigt, wenn Sie auf die letzten drei Links klicken? ——Es ist alles „Sie haben auf den 4. Link geklickt“. Überrascht es Sie? Warum?
Analyse: Da der Ereignishandler element.onclick in der Funktion badClosureExample() zugewiesen ist, wird die anonyme Funktion onclick erst aufgerufen, nachdem die Funktion badClosureExample() abgeschlossen ist (wenn der Benutzer auf den Link klickt). Beim Aufruf muss die Variable i ausgewertet werden. Der Parser sucht zunächst im Ereignishandler, i ist jedoch nicht definiert. Suchen Sie dann in der Funktion badClosureExample(). Sie ist zu diesem Zeitpunkt definiert, aber der Wert von i ist 4 (die Ausführung der for-Schleife wird nur gestoppt, wenn i größer als 4 ist). Daher wird dieser Wert erhalten – genau das, was der Abschluss (anonyme Funktion) tun würde, wenn er eine Variable im Bereich seiner äußeren Funktion (badClosureExample) verwenden würde. Darüber hinaus liegt dies auch daran, dass die anonyme Funktion selbst keine Parameter übergeben kann (und daher ihren eigenen Gültigkeitsbereich nicht verwalten kann).
Wie lässt sich das Problem in diesem Beispiel lösen? Tatsächlich gibt es viele Methoden (Sie können es auch selbst schreiben und sehen). Ich denke, der Code ist relativ einfach und direkt:
function popNum(oNum){ return function(){ alert('您单击的是第'+oNum+'个链接'); } } function badClosureExample(){ for (var i = 1; i <4; i++) { var element = document.getElementById('closureTest' + i); element .onclick =new popNum(i); } }
(2), clevere Verwendung von Verschlüssen zum Binden von Parametern
Trotzdem möchten wir mit dem obigen HTML-Fragment das Auftauchen eines Warnfelds verzögern, wenn der Benutzer auf den ersten Link klickt. Die Antwort besteht darin, die Funktion setTimeout() zu verwenden, die eine Funktion nach einer angegebenen Anzahl von Millisekunden aufruft, wie zum Beispiel:
function goodClosureExample(oMsg){ return function(){ alert(oMsg); }; }
Die Funktion goodClosureExample wird verwendet, um eine anonyme Funktion (Abschluss) zurückzugeben. Und wir können die zurückgegebene anonyme Funktion dazu bringen, den Parameter zu binden, indem wir ihr einen Parameter übergeben, wie zum Beispiel:
window.onload = function(){ var element = document.getElementById('closureTest0'); if (element) { var good = goodClosureExample('这个参数是由闭包绑定的'); element.onclick = function(){ setTimeout(good, 1000); //延迟1秒弹出提示 } } }
3、javascript的垃圾回收原理
(1)、在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收;
(2)、如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。
在js中使用闭包,往往会给javascript的垃圾回收器制造难题。尤其是遇到对象间复杂的循环引用时,垃圾回收的判断逻辑非常复杂,搞不好就有内存泄漏的危险,所以,慎用闭包。ms貌似已经不建议使用闭包了。
希望本文所述对大家JavaScript程序设计有所帮助。