Lassen Sie uns gemeinsam Verschlüsse kennenlernen
Verwandte Lernempfehlungen: Javascript-Video-Tutorial
Vorwort
Abschlüsse werden immer eine Hürde sein, die Front-End-Entwickler bei der Arbeit und in Interviews nicht umgehen können, ob es Ihnen gefällt oder nicht , wird angetroffen. Jeder hat ein anderes Verständnis von Schließung. Hier werde ich über mein eigenes Verständnis von Schließung sprechen. (Wenn es Unstimmigkeiten mit Ihrem Verständnis gibt, beziehen Sie sich bitte auf sich selbst)
So definieren Sie Abschlüsse
Bevor Sie die Definition geben, können Sie sich auch ansehen, wie andere Abschlüsse definieren:
Funktionsobjekte können den Gültigkeitsbereich durchlaufen Ketten stehen in Beziehung zueinander und die Variablen innerhalb des Funktionskörpers können im Funktionsumfang gespeichert werden. Diese Funktion wird in der Informatikliteratur als „Abschluss“ bezeichnet – The Definitive Guide to JavaScript (6. Auflage)
Abschluss bedeutet A Funktion, die Zugriff auf Variablen im Gültigkeitsbereich einer anderen Funktion hat. Eine übliche Methode zum Erstellen eines Abschlusses besteht darin, eine Funktion innerhalb einer anderen Funktion zu erstellen. --Erweiterte Programmierung mit JavaScript (Dritte Ausgabe)
Ein Abschluss erfolgt, wenn sich eine Funktion an den lexikalischen Bereich erinnern und darauf zugreifen kann, in dem sie sich befindet, auch wenn die Funktion außerhalb des aktuellen lexikalischen Bereichs ausgeführt wird. -- JavaScript, das Sie nicht kennen (Band 1)
Obwohl die Beschreibungen in den obigen Absätzen unterschiedlich sind, können Sie nach sorgfältiger Verkostung dennoch einige Gemeinsamkeiten feststellen. Das Wichtigste ist die Verbindung zwischen verschiedenen Bereichen. Natürlich können Sie die obigen Definitionen direkt zitieren (schließlich sind die obigen Definitionen relativ maßgeblich). Hier bevorzugt der Autor die Definition im letzten Absatz und empfiehlt außerdem dringend das Buch „JavaScript You Don't Know“ (Band 1). )“, das es wert ist, sorgfältig und wiederholt gelesen zu werden.
Welche Wissenspunkte sind am Abschluss beteiligt? Es reicht nicht aus, nur eine Definition zu geben, Sie müssen auch untersuchen, welche Wissenspunkte intern beteiligt sind. Im Folgenden sind die Wissenspunkte aufgeführt, die der Autor für nützlich hält.
Umfang und Umfangskette
Tatsächlich weiß der Autor, dass Sie alle daran gedacht haben (nein, daran hat noch niemand gedacht). Jetzt, da jeder den Umfang kennt. Hier werde ich es kurz beschreiben und den Prozess durchgehen.
Geltungsbereich: Eine Reihe von Regeln zum Suchen von Variablen nach Namen. In drei Typen unterteilt: globaler Bereich; Funktionsbereich; Was Sie beachten müssen, ist der Blockbereich, eine neue Spezifikation in ES6. Mit let, const
in geschweiften Klammern {}
definierte Variablen werden an den Gültigkeitsbereich gebunden und können außerhalb der geschweiften Klammern nicht aufgerufen werden.
Hinweis: Es gibt eine vorübergehende tote Zone
zwischen dem Anfang der geschweiften Klammern und vor der Deklaration der let-Variablen (dieser Punkt geht über den Rahmen dieses Artikels hinaus).
{}
里面使用let,const
定义的变量,都会绑定到该作用范围内,花括号以外的地方无法访问。注意:在花括号开始 到 let变量声明之前,存在暂时性死区
(该点不在本文讨论范围)。
作用域链:当不同的作用域 (混~淆~在~一~起~ 呸,不小心出戏了) 圈套在一起时,就形成了作用域链。注意的是,查找方向是从内到外的。
为什么作用域的查找方向是从内到外的呢?这是个很有趣的问题。个人觉得是跟js执行函数的入栈方式决定的(感觉有点偏题了,有兴趣的小伙伴可以去查一下资料)。
词法作用域
函数之所以 可以访问另一个函数作用域的变量(或者说记住当前的作用域并在当前以外的地方访问)的关键点
就是词法作用域
在起作用。这一点很重要,但不是所有人都知道这个知识点,这里简单探讨一下。
在编程界中,存在两种作用域工作模式,一种是被大多数编程语言所采用的
词法作用域
;另一种就是与其相反的动态作用域
(这个不在本文的讨论范围)。
词法作用域: 变量和块的作用域 在 您编写代码的阶段 就已经确定好了,不会随着调用的对象或者地方的不同而改变(感觉跟this相反)。
要不,举个栗子看看吧:
let a = 1; function fn(){ let a = 2; function fn2(){ console.log(a); } return fn2; } let fn3 = fn(); fn3();
从上面的定义可以知道,fn
是一个闭包函数,fn3
拿到了fn2
的指针地址,当fn3
执行的时候,其实是执行fn2
,而里面的a
变量,根据作用域链的查找规则,找到的是fn
作用域内的变量a
Scope-Kette: Wenn verschiedene Scopes zusammengeschlossen werden, entsteht eine Scope-Kette. Beachten Sie, dass die Suchrichtung von innen nach außen verläuft.

lexikalischer Bereich
Der entscheidende Punkt< /code> bedeutet, dass der <code>lexikalische Bereich
am Werk ist. Das ist wichtig, aber nicht jeder kennt diesen Wissenspunkt. Lassen Sie uns ihn hier kurz besprechen. In der Programmierwelt gibt es zwei Arbeitsmodi: Der eine ist der lexikalische Bereich
, der von den meisten Programmiersprachen verwendet wird; der andere ist der entgegengesetzte dynamische Bereich
(Dies würde den Rahmen dieses Artikels sprengen).
function Fn(obj){ with(obj){ a = 2; } } var o1 = { a:1 } var o2 = { b:1 } Fn(o1); console.log(o1.a); //2 Fn(o2); console.log(o2.a); //undefined; console.log(a); //2 a被泄漏到全局里面去了 // 这是with的一个副作用, 如果当前词法作用域没有该属性,会在全局创建一个
fn
eine Abschlussfunktion ist und fn3
erhält Die Zeigeradresse Wenn <code>fn3
ausgeführt wird, führt fn2 tatsächlich fn2
und die darin enthaltene Variable a
entsprechend dem Suchbereich aus Die Regel der Kette findet die Variable a
im Bereich von fn
, sodass die endgültige Ausgabe 2 und nicht 1 ist. (Sie können das Bild unten sehen)🎜🎜🎜🎜🎜🎜🎜Off-Topic: Wie kann man den lexikalischen Umfang betrügen? 🎜🎜Obwohl der lexikalische Umfang statisch ist, gibt es dennoch Möglichkeiten, ihn auszutricksen, um dynamische Effekte zu erzielen. 🎜第一种方法是使用eval. eval可以把字符串解析成一个脚本来运行,由于在词法分析阶段,无法预测eval运行的脚本,所以不会对其进行优化分析。
第二种方法是with. with通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。with本身比较难掌握,使用不当容易出现意外情况(如下例子),不推荐使用 -.-
function Fn(obj){ with(obj){ a = 2; } } var o1 = { a:1 } var o2 = { b:1 } Fn(o1); console.log(o1.a); //2 Fn(o2); console.log(o2.a); //undefined; console.log(a); //2 a被泄漏到全局里面去了 // 这是with的一个副作用, 如果当前词法作用域没有该属性,会在全局创建一个
闭包能干啥?
闭包的使用场景可多了,平时使用的插件或者框架,基本上都有闭包的身影,可能您没留意过罢了。下面笔者列举一些比较常见的场景。
模拟私有变量和方法,进一步来说可以是模拟
模块化
;目前常用的AMD,CommonJS等模块规范,都是利用闭包的思想;柯里化函数或者偏函数;利用闭包可以把参数分成多次传参。如下面代码:
// 柯里化函数 function currying(fn){ var allArgs = []; function bindCurry(){ var args = [].slice.call(arguments); allArgs = allArgs.concat(args); return bindCurry; } bindCurry.toString = function(){ return fn.apply(null, allArgs); }; return bindCurry; }
实现防抖或者节流函数;
实现缓存结果(记忆化)的辅助函数:
// 该方法适合缓存结果不易改变的函数 const memorize = fn => { let memorized = false; let result = undefined; return (...args) => { if (memorized) { return result; } else { result = fn.apply(null,args); memorized = true; fn = undefined; return result; } }; };
如何区分闭包?
说了那么多,我怎么知道自己写的代码是不是闭包呢?先不说新手,有些代码的确隐藏的深,老鸟不仔细看也可能发现不了。 那有没有方法可以帮助我们区分一个函数是不是闭包呢?答案是肯定的,要学会善于利用周边的工具资源,比如浏览器。
打开常用的浏览器(chrome或者其他),在要验证的代码中打上debugger断点,然后看控制台,在scope里面的Closure(闭包)里面是否有该函数(如下图)。

闭包真的会导致内存泄漏?
答案是有可能。内存泄漏的原因在于垃圾回收(GC)无法释放变量的内存,导致运行一段时候后,可用内存越来越少,最终出现内存泄漏的情况。常见的内存泄漏场景有4种:全局变量;闭包引用;DOM事件绑定;不合理使用缓存。其中,闭包导致内存泄漏都是比较隐蔽的,用肉眼查看代码判断是比较难,我们可用借助chrome浏览器的Memory标签栏工具来调试。由于篇幅问题,不展开说明了,有兴趣自己去了解一下如何使用。
想了解更多编程学习,敬请关注php培训栏目!
Das obige ist der detaillierte Inhalt vonLassen Sie uns gemeinsam Verschlüsse kennenlernen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



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.

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.

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.

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

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.

Abschlüsse in Java ermöglichen es inneren Funktionen, auf äußere Bereichsvariablen zuzugreifen, selbst wenn die äußere Funktion beendet wurde. Durch anonyme innere Klassen implementiert, enthält die innere Klasse einen Verweis auf die äußere Klasse und hält die äußeren Variablen aktiv. Schließungen erhöhen die Codeflexibilität, Sie müssen sich jedoch des Risikos von Speicherverlusten bewusst sein, da Verweise auf externe Variablen durch anonyme innere Klassen diese Variablen am Leben halten.

Wie kann man Speicherlecks in Schließungen verhindern? Der Verschluss ist eine der leistungsstärksten Funktionen in JavaScript, die die Verschachtelung von Funktionen und die Kapselung von Daten ermöglicht. Schließungen sind jedoch auch anfällig für Speicherverluste, insbesondere bei asynchronen und Timer-Operationen. In diesem Artikel wird erläutert, wie Speicherlecks bei Abschlüssen verhindert werden, und es werden spezifische Codebeispiele bereitgestellt. Speicherlecks treten normalerweise auf, wenn ein Objekt nicht mehr benötigt wird, der von ihm belegte Speicher jedoch aus irgendeinem Grund nicht freigegeben werden kann. In einem Abschluss, wenn eine Funktion auf externe Variablen und diese Variablen verweist

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.
