Heim Web-Frontend js-Tutorial Ein erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen

Ein erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen

Nov 25, 2019 pm 05:00 PM
js 闭包

Ein erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen

Der alte Treiber wird Ihnen helfen, die verschiedenen Fallstricke von JS-Abschlüssen gründlich zu verstehen

Abschlüsse sind js Gängige Entwicklungstechniken, was sind Verschlüsse?

Ein Abschluss bezieht sich auf eine Funktion, die auf Variablen im Rahmen einer anderen Funktion zugreifen kann. Um es klar auszudrücken: Ein Abschluss ist eine Funktion, die im Rahmen anderer Funktionen auf Variablen zugreifen kann. zB:

function outer() {
     var  a = '变量1'
     var  inner = function () {
            console.info(a)
     }
    return inner    // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}
Nach dem Login kopieren

Viele Leute verstehen die Beziehung zwischen anonymen Funktionen und Abschlüssen nicht. Tatsächlich werden Abschlüsse aus der Perspektive des Bereichs definiert, da inner auf Variablen im äußeren Bereich zugreift, also ist inner eine Abschlussfunktion. Obwohl die Definition sehr einfach ist, gibt es viele Fallstricke, wie z. B. diesen Zeiger und den Umfang der Variablen. Eine kleine Nachlässigkeit kann zu Speicherverlusten führen. Lassen Sie uns das Problem beiseite legen und über eine Frage nachdenken: Warum können Abschlussfunktionen auf den Umfang anderer Funktionen zugreifen?

Js-Funktionen aus der Perspektive des Stapels betrachten

Grundvariablen Der Wert von wird im Allgemeinen im Stapelspeicher gespeichert, während der Wert der Objekttypvariablen im Heapspeicher gespeichert wird und der Stapelspeicher die entsprechende Raumadresse speichert. Grundlegende Datentypen: Zahl, Boolescher Wert, Undefiniert, Zeichenfolge, Null.

var  a = 1   //a是一个基本类型
var  b = {m: 20 }   //b是一个对象
Nach dem Login kopieren

entspricht dem Speicher:

Ein erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen

Wenn wir b={m:30} ausführen, gibt es ein neues Objekt {m:30} im Heap-Speicher, b im Stapelspeicher zeigt auf die neue Raumadresse (zeigt auf {m: 30}), und das ursprüngliche {m: 20} im Heap-Speicher wird von der Programm-Engine als Müll gesammelt, wodurch Speicherplatz gespart wird. Wir wissen, dass js-Funktionen auch Objekte sind und auch im Heap- und Stack-Speicher gespeichert werden. Schauen wir uns die Konvertierung an:

var a = 1;
function fn(){
    var b = 2;
    function fn1(){
        console.log(b);
    }
    fn1();
}
fn();
Nach dem Login kopieren

Ein erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen

**

Der Stapel ist eine First-In-Last-Out-Datenstruktur:

1 Bevor wir fn ausführen, befinden wir uns in der globalen Ausführungsumgebung (der Browser ist der Fensterbereich) und es gibt eine Variable a in der globale Bereich;

2 Geben Sie fn ein. Diese Umgebung enthält die Variable b und das Funktionsobjekt fn1 Umgebung und die globale Ausführungsumgebung

3 Geben Sie fn1 ein. Zu diesem Zeitpunkt wird der Stapelspeicher eine Ausführungsumgebung von fn1 übertragen. Es sind keine anderen Variablen darin definiert, aber wir können auf die Variablen in fn und zugreifen globale Ausführungsumgebung, denn wenn das Programm auf die Variablen zugreift, wird es in den untersten Stapel verschoben. Wenn Sie feststellen, dass in der globalen Ausführungsumgebung keine entsprechende Variable vorhanden ist, gibt das Programm einen unterdefinierten Fehler aus.

4 Während fn1() ausgeführt wird, wird die Ausführungsumgebung von fn1 durch cup zerstört, und wenn fn() ausgeführt wird, wird auch die Ausführungsumgebung von fn zerstört, sodass nur die globale Ausführungsumgebung übrig bleibt Jetzt gibt es keine b-Variablen und fn1-Funktionsobjekte, nur a und fn (der Funktionsdeklarationsbereich liegt unter dem Fenster)

**

Der Zugriff auf eine Variable innerhalb einer Funktion wird anhand der beurteilt Funktionsbereichskette Gibt an, ob die Variable vorhanden ist und die Funktionsbereichskette vom Programm entsprechend dem Ausführungsumgebungsstapel initialisiert wird, in dem sich die Funktion befindet. Im obigen Beispiel drucken wir also die Variable b in fn1 und suchen die entsprechende fn-Ausführungsumgebung gemäß der Bereichskette der fn1-Variablen b. Wenn das Programm also eine Funktion aufruft, führt es die folgende Arbeit aus: Bereiten Sie die Ausführungsumgebung, die anfängliche Funktionsbereichskette und das Argumentparameterobjekt vor >Wenn das Programm die Ausführung von var inner = OUTER () beendet, wird die Ausführungsumgebung von OUTER tatsächlich nicht zerstört, da die darin enthaltene Variable a immer noch von der Funktionsbereichskette von Inner () referenziert wird. Das Buch „JavaScript Advanced Programming“ empfiehlt: „Da Schließungen den Umfang der Funktion übernehmen, die sie enthält, nehmen sie mehr Inhalt ein als andere Funktionen.“ Die Verwendung von Schließungen führt zu einer übermäßigen Speichernutzung.

Jetzt verstehen wir den Abschluss, den entsprechenden Geltungsbereich und die Geltungsbereichskette, kehren zum Thema zurück:

Punkt 1: Die referenzierten Variablen können sich ändern

function outer() {
     var  a = '变量1'
     var  inner = function () {
            console.info(a)
     }
    return inner    // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}
var  inner = outer()   // 获得inner闭包函数
inner()   //"变量1"
Nach dem Login kopieren

Es scheint, dass jede Abschlussfunktion im Ergebnis die entsprechende Zahl ausgibt, 1, 2, 3, 4, ..., 10. Dies ist jedoch nicht der Fall, da jede Abschlussfunktion auf die Variable i in der äußeren Ausführungsumgebung zugreift. Variable i, am Ende der Schleife ist i zu 10 geworden, also wird jede Abschlussfunktion ausgeführt und das Ergebnis gibt 10, 10, ..., 10 ausWie kann dieses Problem gelöst werden?

function outer() {
      var result = [];
      for (var i = 0; i<10; i++){
        result.[i] = function () {
            console.info(i)
        }
     }
     return result
}
Nach dem Login kopieren

Punkt 2: Das weist auf das Problem hin

function outer() {
      var result = [];
      for (var i = 0; i<10; i++){
        result.[i] = function (num) {
             return function() {
                   console.info(num);    // 此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样
             }
        }(i)
     }
     return result
}
Nach dem Login kopieren

Punkt 3: Speicherverlustproblem

var object = {
     name: &#39;&#39;object",
     getName: function() {
        return function() {
             console.info(this.name)
        }
    }
}
object.getName()()    // underfined
// 因为里面的闭包函数是在window作用域下执行的,也就是说,this指向window
Nach dem Login kopieren

Tipp 1: Verwenden Sie Abschlüsse, um rekursive Aufrufprobleme zu lösen

function  showId() {
    var el = document.getElementById("app")
    el.onclick = function(){
      aler(el.id)   // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
}
// 改成下面
function  showId() {
    var el = document.getElementById("app")
    var id  = el.id
    el.onclick = function(){
      aler(id)   // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
    el = null    // 主动释放el
}
Nach dem Login kopieren

** Tipp 2: Verwenden Sie Abschlüsse, um den Gültigkeitsbereich auf Blockebene zu imitieren**

es6 ist noch nicht verfügbar. Zuvor gab es ein Problem mit der Variablenförderung, wenn var zum Definieren von Variablen verwendet wurde, z. B.:

function  factorial(num) {
   if(num<= 1) {
       return 1;
   } else {
      return num * factorial(num-1)
   }
}
var anotherFactorial = factorial
factorial = null
anotherFactorial(4)   // 报错 ,因为最好是return num* arguments.callee(num-1),arguments.callee指向当前执行函数,但是在严格模式下不能使用该属性也会报错,所以借助闭包来实现
// 使用闭包实现递归
function newFactorial = (function f(num){
    if(num<1) {return 1}
    else {
       return num* f(num-1)
    }
}) //这样就没有问题了,实际上起作用的是闭包函数f,而不是外面的函数newFactorial
Nach dem Login kopieren
Natürlich werden die meisten von ihnen jetzt mit let und const von es6 definiert.

Dieser Artikel ist hier zu Ende. Weitere spannende Inhalte finden Sie in der Spalte

JavaScript-Video-Tutorial
auf der chinesischen PHP-Website!

Das obige ist der detaillierte Inhalt vonEin erfahrener Fahrer wird Ihnen helfen, die verschiedenen Fallstricke von JS-Verschlüssen gründlich zu verstehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Empfohlen: Ausgezeichnetes JS-Open-Source-Projekt zur Gesichtserkennung und -erkennung Empfohlen: Ausgezeichnetes JS-Open-Source-Projekt zur Gesichtserkennung und -erkennung Apr 03, 2024 am 11:55 AM

Die Technologie zur Gesichtserkennung und -erkennung ist bereits eine relativ ausgereifte und weit verbreitete Technologie. Derzeit ist JS die am weitesten verbreitete Internetanwendungssprache. Die Implementierung der Gesichtserkennung und -erkennung im Web-Frontend hat im Vergleich zur Back-End-Gesichtserkennung Vor- und Nachteile. Zu den Vorteilen gehören die Reduzierung der Netzwerkinteraktion und die Echtzeiterkennung, was die Wartezeit des Benutzers erheblich verkürzt und das Benutzererlebnis verbessert. Die Nachteile sind: Es ist durch die Größe des Modells begrenzt und auch die Genauigkeit ist begrenzt. Wie implementiert man mit js die Gesichtserkennung im Web? Um die Gesichtserkennung im Web zu implementieren, müssen Sie mit verwandten Programmiersprachen und -technologien wie JavaScript, HTML, CSS, WebRTC usw. vertraut sein. Gleichzeitig müssen Sie auch relevante Technologien für Computer Vision und künstliche Intelligenz beherrschen. Dies ist aufgrund des Designs der Webseite erwähnenswert

Was bedeutet der Abschluss im C++-Lambda-Ausdruck? Was bedeutet der Abschluss im C++-Lambda-Ausdruck? Apr 17, 2024 pm 06:15 PM

In C++ ist ein Abschluss ein Lambda-Ausdruck, der auf externe Variablen zugreifen kann. Um einen Abschluss zu erstellen, erfassen Sie die äußere Variable im Lambda-Ausdruck. Abschlüsse bieten Vorteile wie Wiederverwendbarkeit, Ausblenden von Informationen und verzögerte Auswertung. Sie sind in realen Situationen nützlich, beispielsweise bei Ereignishandlern, bei denen der Abschluss auch dann noch auf die äußeren Variablen zugreifen kann, wenn diese zerstört werden.

Wie implementiert man einen Abschluss im C++-Lambda-Ausdruck? Wie implementiert man einen Abschluss im C++-Lambda-Ausdruck? Jun 01, 2024 pm 05:50 PM

C++-Lambda-Ausdrücke unterstützen Abschlüsse, die Funktionsbereichsvariablen speichern und sie für Funktionen zugänglich machen. Die Syntax lautet [capture-list](parameters)->return-type{function-body}. Capture-Liste definiert die zu erfassenden Variablen. Sie können [=] verwenden, um alle lokalen Variablen nach Wert zu erfassen, [&], um alle lokalen Variablen nach Referenz zu erfassen, oder [Variable1, Variable2,...], um bestimmte Variablen zu erfassen. Lambda-Ausdrücke können nur auf erfasste Variablen zugreifen, den ursprünglichen Wert jedoch nicht ändern.

Was sind die Vor- und Nachteile von Abschlüssen in C++-Funktionen? Was sind die Vor- und Nachteile von Abschlüssen in C++-Funktionen? Apr 25, 2024 pm 01:33 PM

Ein Abschluss ist eine verschachtelte Funktion, die auf Variablen im Bereich der äußeren Funktion zugreifen kann. Zu ihren Vorteilen gehören Datenkapselung, Zustandserhaltung und Flexibilität. Zu den Nachteilen gehören der Speicherverbrauch, die Auswirkungen auf die Leistung und die Komplexität des Debuggens. Darüber hinaus können Abschlüsse anonyme Funktionen erstellen und diese als Rückrufe oder Argumente an andere Funktionen übergeben.

Lösen Sie das durch Schließungen verursachte Speicherverlustproblem Lösen Sie das durch Schließungen verursachte Speicherverlustproblem Feb 18, 2024 pm 03:20 PM

Titel: Durch Abschlüsse und Lösungen verursachte Speicherlecks Einführung: Abschlüsse sind ein sehr verbreitetes Konzept in JavaScript, das internen Funktionen den Zugriff auf Variablen externer Funktionen ermöglicht. Allerdings können Schließungen bei falscher Verwendung zu Speicherverlusten führen. In diesem Artikel wird das durch Schließungen verursachte Speicherverlustproblem untersucht und Lösungen sowie spezifische Codebeispiele bereitgestellt. 1. Durch Schließungen verursachte Speicherlecks Das Merkmal von Schließungen besteht darin, dass interne Funktionen auf Variablen externer Funktionen zugreifen können, was bedeutet, dass in Schließungen referenzierte Variablen nicht durch Müll gesammelt werden. Bei unsachgemäßer Verwendung

Der Einfluss von Funktionszeigern und -abschlüssen auf die Golang-Leistung Der Einfluss von Funktionszeigern und -abschlüssen auf die Golang-Leistung Apr 15, 2024 am 10:36 AM

Die Auswirkungen von Funktionszeigern und -abschlüssen auf die Go-Leistung sind wie folgt: Funktionszeiger: Etwas langsamer als direkte Aufrufe, aber verbessert die Lesbarkeit und Wiederverwendbarkeit. Schließungen: Normalerweise langsamer, kapseln aber Daten und Verhalten. Praktischer Fall: Funktionszeiger können Sortieralgorithmen optimieren und Abschlüsse können Ereignishandler erstellen, aber sie bringen Leistungseinbußen mit sich.

Die Beziehung zwischen js und vue Die Beziehung zwischen js und vue Mar 11, 2024 pm 05:21 PM

Die Beziehung zwischen js und vue: 1. JS als Eckpfeiler der Webentwicklung; 2. Der Aufstieg von Vue.js als Front-End-Framework; 3. Die komplementäre Beziehung zwischen JS und Vue; Vue.

Verkettete Aufrufe und Schließungen von PHP-Funktionen Verkettete Aufrufe und Schließungen von PHP-Funktionen Apr 13, 2024 am 11:18 AM

Ja, die Einfachheit und Lesbarkeit des Codes können durch verkettete Aufrufe und Abschlüsse optimiert werden: Verkettete Aufrufe verknüpfen Funktionsaufrufe in einer fließenden Schnittstelle. Abschlüsse erstellen wiederverwendbare Codeblöcke und greifen auf Variablen außerhalb von Funktionen zu.

See all articles