Heim >Web-Frontend >js-Tutorial >Wie verwende ich Verschlüsse in js?
In diesem Artikel werden hauptsächlich JavaScript-Abschlüsse vorgestellt. Viele fortgeschrittene Anwendungen sind auf Abschlüsse angewiesen, um
Funktionen als Rückgabewerte zu implementieren
Neben der Annahme von Funktionen als Parameter können Funktionen höherer Ordnung auch Funktionen als Ergebniswerte zurückgeben.
Lassen Sie uns eine Summierung von Array
implementieren. Normalerweise ist die Summationsfunktion wie folgt definiert:
function sum(arr) { return arr.reduce(function (x, y) { return x + y; }); } sum([1, 2, 3, 4, 5]); // 15
Wenn Sie jedoch nicht sofort summieren müssen, sondern im folgenden Code, was dann? sollten wir das tun, wenn wir es nach Bedarf erneut berechnen? Anstatt das Summationsergebnis zurückzugeben, können Sie die Summationsfunktion zurückgeben!
function lazy_sum(arr) { var sum = function () { return arr.reduce(function (x, y) { return x + y; }); } return sum; }
Wenn wir lazy_sum()
aufrufen, wird nicht das Summierungsergebnis zurückgegeben, sondern die Summationsfunktion:
var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
Das Ergebnis der Summe wird tatsächlich berechnet, wenn die Funktion f aufgerufen wird:
f(); // 15
In diesem Im Beispiel definieren wir die Funktion lazy_sum
in der Funktion sum
, und die interne Funktion sum
kann auf die Parameter und lokalen Variablen der externen Funktion lazy_sum
verweisen, wenn lazy_sum
gibt die Funktion sum
zurück, die relevanten Parameter und Variablen werden in der zurückgegebenen Funktion gespeichert. Diese Programmstruktur namens „Closure“ hat große Leistungsfähigkeit.
Bitte beachten Sie, dass beim Aufruf von lazy_sum()
jeder Aufruf eine neue Funktion zurückgibt, auch wenn dieselben Parameter übergeben werden:
var f1 = lazy_sum([1, 2, 3, 4, 5]); var f2 = lazy_sum([1, 2, 3, 4, 5]); f1 === f2; // false
f1()
und f2()
haben keinen Einfluss aufeinander.
Abschluss
Beachten Sie, dass die zurückgegebene Funktion auf die lokale Variable arr
innerhalb ihrer Definition verweist. Wenn also eine Funktion nach einer Funktion zurückkehrt, Die neue Funktion referenziert auch ihre internen lokalen Variablen. Daher sind Abschlüsse einfach zu verwenden, aber nicht einfach zu implementieren.
Ein weiteres zu beachtendes Problem besteht darin, dass die zurückgegebene Funktion nicht sofort ausgeführt wird, sondern erst ausgeführt wird, wenn f() aufgerufen wird. Schauen wir uns ein Beispiel an:
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push(function () { return i * i; }); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];
Im obigen Beispiel wird bei jeder Schleife eine neue Funktion erstellt, und die erstellte Funktion ist dann „Alle“. Drei Funktionen werden zu einem Array
hinzugefügt und zurückgegeben.
Man könnte meinen, dass das Ergebnis des Aufrufs von f1()
, f2()
und f3()
1
, 4
, 9
sein sollte, aber das tatsächliche Ergebnis ist:
f1(); // 16 f2(); // 16 f3(); // 16
Alle 16
! Der Grund dafür ist, dass die zurückgegebene Funktion auf die Variable i
verweist, diese aber nicht sofort ausgeführt wird. Wenn alle drei Funktionen zurückkehren, ist die Variable i, auf die sie sich beziehen, zu 4
geworden, sodass das Endergebnis 16
ist.
Bei der Rückgabe eines Abschlusses ist Folgendes zu beachten: Die Rückgabefunktion sollte keine Schleifenvariablen oder Variablen referenzieren, die sich später ändern.
Was passiert, wenn Sie auf eine Schleifenvariable verweisen müssen? Die Methode besteht darin, eine weitere Funktion zu erstellen und den Parameter der Funktion zu verwenden, um den aktuellen Wert der Schleifenvariablen zu binden. Unabhängig davon, wie sich die Schleifenvariable anschließend ändert, wird der an den Parameter gebundene Wert verwendet Die Funktion bleibt unverändert:
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push((function (n) { return function () { return n * n; } })(i)); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2]; f1(); // 1 f2(); // 4 f3(); // 9
Beachten Sie, dass die Syntax von „Erstellen Sie eine anonyme Funktion und führen Sie sie sofort aus.“ " wird hier verwendet:
(function (x) { return x * x; })(3); // 9
Um eine anonyme Funktion zu erstellen und sofort auszuführen, können Sie theoretisch schreiben:
function (x) { return x * x } (3);
Aufgrund von JavaScript-Syntax Parsing-Problemen wird jedoch ein SyntaxError-Fehler gemeldet, sodass die gesamte Funktionsdefinition in Klammern eingeschlossen werden muss:
(function (x) { return x * x }) (3);
Normalerweise kann eine anonyme Funktion, die sofort ausgeführt wird, den Funktionskörper trennen, normalerweise wie folgt geschrieben:
(function (x) { return x * x; })(3);
Nachdem ich so viel gesagt habe: Ist es geschlossen? Ist der Zweck des Pakets nur, eine Funktion zurückzugeben und dann die Ausführung zu verzögern?
Natürlich nicht! Verschlüsse sind sehr kraftvoll. Beispiel:
In objektorientierten Programmiersprachen wie Java und C++ können Sie zum Kapseln einer privaten Variablen in einem Objekt private verwenden, um eine Mitgliedsvariable zu ändern.
In Sprachen, die keinen class
-Mechanismus haben und nur über Funktionen verfügen, kann eine private Variable auch mit Hilfe von Abschlüssen gekapselt werden. Wir erstellen einen Zähler mit JavaScript:
'use strict'; function create_counter(initial) { var x = initial || 0; return { inc: function () { x += 1; return x; } } }
Es funktioniert so:
var c1 = create_counter(); c1.inc(); // 1 c1.inc(); // 2 c1.inc(); // 3 var c2 = create_counter(10); c2.inc(); // 11 c2.inc(); // 12 c2.inc(); // 13
Im zurückgegebenen Objekt ist ein Abschluss implementiert, der die lokale Variable x
trägt, und auf die Variable x
kann von externem Code überhaupt nicht zugegriffen werden. Mit anderen Worten, ein Abschluss ist eine Funktion, die einen Zustand trägt, und sein Zustand kann vollständig vor der Außenwelt verborgen bleiben.
闭包还可以把多参数的函数变成单参数的函数。例如,要计算xy可以用Math.pow(x, y)
函数,不过考虑到经常计算x2或x3,我们可以利用闭包创建新的函数pow2
和pow3
:
function make_pow(n) { return function (x) { return Math.pow(x, n); } } // 创建两个新函数: var pow2 = make_pow(2); var pow3 = make_pow(3); pow2(5); // 25 pow3(7); // 343
脑洞大开
很久很久以前,有个叫阿隆佐·邱奇的帅哥,发现只需要用函数,就可以用计算机实现运算,而不需要0、1、2、3
这些数字和+、-、*、/
这些符号。
JavaScript支持函数,所以可以用JavaScript用函数来写这些计算。来试试:
'use strict'; // 定义数字0: var zero = function (f) { return function (x) { return x; } }; // 定义数字1: var one = function (f) { return function (x) { return f(x); } }; // 定义加法: function add(n, m) { return function (f) { return function (x) { return m(f)(n(f)(x)); } } }
Das obige ist der detaillierte Inhalt vonWie verwende ich Verschlüsse in js?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!