Heim > Web-Frontend > js-Tutorial > Hauptteil

Verschluss von vorne nach hinten

PHPz
Freigeben: 2023-09-02 16:09:03
Original
1155 Leute haben es durchsucht

In JavaScript werden Verschlüsse oft als mysteriöse Kunst betrachtet. Sobald Sie sie beherrschen, können Sie wirklich erstaunliches JavaScript schreiben. Dieser Artikel gibt Ihnen eine kurze Einführung in die Magie von JavaScript-Abschlüssen.


Was ist Schließung?

Eine der wichtigsten Tatsachen von JavaScript ist, dass „alles“ ein Objekt ist. Dazu gehört natürlich auch die Funktionalität.

Ein Abschluss ist nichts anderes als ein Funktionsobjekt mit einem zugehörigen Bereich, in dem die Variablen der Funktion aufgelöst werden.

Verschlüsse haben ihren Namen von der Art und Weise, wie ihr Inhalt
geschlossen

ist. Betrachten Sie den folgenden JavaScript-Code:

topping = "anchovi";
function pizzaParty(numSlices) {
	var topping = "pepperoni",

	innerFunction = function() {
		var topping = "ham";
		console.log(" .....But put " + topping + " on " + numSlices + " slices");
	};

	console.log("This pizza is all about the " + topping);

	innerFunction();
}
pizzaParty(3);
Nach dem Login kopieren
Wenn Sie Ihre Lieblingskonsole starten und diesen bösen Jungen starten, erhalten Sie eine köstliche Meldung mit dem Effekt: „Diese Pizza besteht nur aus Peperoni … aber legen Sie den Schinken auf drei Scheiben.“ Das Beispiel veranschaulicht einige Schlüsselkonzepte JavaScript, das für die Beherrschung von Abschlüssen unerlässlich ist.

Ein Abschluss ist ein Funktionsobjekt

Wie viele Funktionsobjekte gibt es im obigen Code? Nun... wir haben

. Jedes Funktionsobjekt verfügt über einen eigenen Satz Variablen, die innerhalb des

UmfangspizzaParty 函数,并且嵌套在该函数中的是 innerFunction。数学并不总是我的强项,但在我的书中 1 + 1 = 2 jeder Funktion aufgelöst werden. Ein Abschluss hat seinen eigenen Geltungsbereich

Abschlüsse können ohne eine solide Grundlage im Umfang nicht vollständig verstanden werden. Der Scoping-Mechanismus von JavaScript ermöglicht es jeder Funktion, ihre eigene

-Variable zu haben, ohne die wir möglicherweise zu viel Peperoni, zu wenig Schinken oder *keuch*... ein paar Sardellen auf unserer Pizzaparty bekommen würden. Lassen Sie uns ein einfaches Beispiel verwenden, um diese Idee besser zu veranschaulichen.

topping

Verschluss von vorne nach hinten

Funktionen werden mit dem Gültigkeitsbereich ausgeführt, der zum Zeitpunkt der Definition der Funktion gültig war. Es hat nichts mit dem gültigen Bereich zu tun, wenn die Funktion aufgerufen wird.

Variable Helfer arbeiten von außen nach innen

Grüne Pfeile zeigen die Zugänglichkeit von außen nach innen an. Auf Variablen, die im Gültigkeitsbereich außerhalb einer Funktion definiert sind, kann innerhalb der Funktion zugegriffen werden.

Wenn wir die Variable

in der Funktion pizzaParty weglassen, erhalten wir eine Meldung wie „Bei dieser Pizza dreht sich alles um die Sardellen“, da sich pizzaParty jedoch in einem eigenen Bereich befindet Es gibt eine

-Variable im Inneren; diese salzigen Idioten kommen nie in die Nähe unserer Pizzaparty. pizzaParty 函数中省略 topping 变量,那么我们会收到类似“This Pizza is all about the anchovi”的消息,但由于 pizzaParty 在其自己的范围内有一个 topping

Ebenso kann man von

reichen. innerFunction 内部访问 numSlices 参数,因为它是在上面的范围中定义的 - 在本例中是 pizzaParty

Variable Barrierefreiheit funktioniert nicht von innen nach außen

Der rote Pfeil zeigt an, dass auf Variablen innerhalb des Gültigkeitsbereichs einer Funktion niemals außerhalb dieser Funktion zugegriffen werden kann. Dies geschieht nur, wenn die Variable eine der folgenden Bedingungen erfüllt:

    Mit dem Schlüsselwort
  1. . var
  2. Variablen sind Parameter von Funktionen oder externen Funktionen.
  3. Diese Variable ist eine verschachtelte Funktion.
Wenn Sie beim Festlegen einer Variablen das Schlüsselwort

weglassen, setzt JavaScript die Variable mit dem nächsten Namen in der äußeren Funktion bis hin zum globalen Bereich. In unserem Beispiel kann also auf ham var 关键字将导致 JavaScript 在外部函数中设置最接近的命名变量,一直到全局范围。因此,使用我们的示例,无法从 pizzaParty 访问 innerFunction 中的火腿 topping,并且无法在 anchovi 所在的全局范围内访问 pizzaParty 中的意大利辣香肠 topping in innerFunction nicht von pizzaParty und in pizzaParty nicht aus dem globalen Bereich zugegriffen werden, in dem sich anchovi befindet Peperoni

.

JavaScript verwendet den lexikalischen Bereich

Lexikalischer Gültigkeitsbereich bedeutet, dass die Funktion unter Verwendung des Variablenbereichs ausgeführt wird, der zum Zeitpunkt der Definition der Funktion gültig war. Es hat nichts mit dem gültigen Bereich zu tun, wenn die Funktion aufgerufen wird. Diese Tatsache ist entscheidend, um die Kraft von Schließungen freizusetzen.

Nachdem wir nun verstanden haben, was ein Abschluss ist und was der Umfang eines Abschlusses bedeutet, wollen wir uns mit einigen klassischen Anwendungsfällen befassen.

Verwenden Sie Abschlüsse, um die Privatsphäre zu schützen

Schließungen sind eine

Möglichkeit, Code vor der Öffentlichkeit zu verbergen. Durch Schließungen können Sie ganz einfach private Mitglieder haben, die von der Außenwelt isoliert sind:
(function(exports){

	function myPrivateMultiplyFunction(num,num2) {
		return num * num2;
	}

	//equivalent to window.multiply = function(num1,num2) { ...
	exports.multiply = function(num1,num2) {
		console.log(myPrivateMultiplyFunction(num1,num2));
	}

})(window);
Nach dem Login kopieren

Schließungen machen es einfach, private Mitglieder zu haben, die von der Außenwelt isoliert sind.

Lassen Sie es uns aufschlüsseln. Unser Funktionsobjekt der obersten Ebene ist eine anonyme Funktion:

(function(exports){
	
})(window);
Nach dem Login kopieren
window),这样我们就可以“导出”一个公共函数,但隐藏其他所有函数。因为函数 myPrivateMultiplyFunction Wir rufen diese anonyme Funktion sofort auf. Wir übergeben ihm den globalen Kontext (in diesem Fall

, der eine verschachtelte Funktion ist und nur innerhalb unseres Abschlussbereichs existiert; wir können ihn also überall in diesem Bereich und nur innerhalb dieses Bereichs verwenden.

myPrivateMultiplyFunction JavaScript behält einen Verweis auf unsere private Funktion zur Verwendung innerhalb der Multiplikationsfunktion bei, ist jedoch außerhalb des Abschlusses nicht zugänglich

. Versuchen wir Folgendes: 🎜
multiply(2,6) // => 12
myPrivateMultiplyFunction(2,6) // => ReferenceError: myPrivateMultiplyFunction is not defined
Nach dem Login kopieren

闭包允许我们定义一个供私人使用的函数,同时仍然允许我们控制世界其他地方所看到的内容。闭包还能做什么?


使用闭包进行元编程

在生成代码时,闭包非常方便。厌倦了记住键盘事件的所有那些烦人的键代码?一种常见的技术是使用键映射:

var KeyMap = {
	"Enter":13,
	"Shift":16,
	"Tab":9,
	"LeftArrow":37
};
Nach dem Login kopieren

然后,在键盘事件中,我们要检查是否按下了某个键:

var txtInput = document.getElementById('myTextInput');
txtInput.onkeypress = function(e) {
	var code = e.keyCode || e.which //usual fare for getting the pressed key
	if (code === KeyMap.Enter) {
	    console.log(txtInput.value);
	}
}
Nach dem Login kopieren

捕捉瞬间

上面的例子并不是最糟糕的,但是我们可以使用元编程和闭包来做出更好的解决方案。使用我们现有的 KeyMap 对象,我们可以生成一些有用的函数:

for (var key in KeyMap) {

	//access object with array accessor to set "dyanamic" function name
	KeyMap["is" + key] = (function(compare) {
		return function(ev) {
			var code = ev.keyCode || ev.which;
			return code === compare;
		}
	})(KeyMap[key]);

}
Nach dem Login kopieren

闭包非常强大,因为它们可以捕获定义它们的函数的局部变量和参数绑定。

此循环为 KeyMap 中的每个键生成一个 is 函数,并且我们的 txtInput.onkeypress 函数变得更具可读性:

var txtInput = document.getElementById('myTextInput');
txtInput.onkeypress = function(e) {
	if(KeyMap.isEnter(e)) {
		console.log(txtInput.value);
	}
}
Nach dem Login kopieren

魔法从这里开始:

KeyMap["is" + key] = (function(compare){
	
})(KeyMap[key]); //invoke immediately and pass the current value at KeyMap[key]
Nach dem Login kopieren

当我们循环 KeyMap 中的键时,我们将该键引用的值传递给匿名外部函数并立即调用它。这将该值绑定到该函数的 compare 参数。

我们感兴趣的闭包是我们从匿名函数内部返回的闭包:

return function(ev) {
	var code = ev.keyCode || ev.which;
	return code === compare;
}
Nach dem Login kopieren

请记住,函数是在定义函数时的作用域内执行的。 compare 参数绑定到循环迭代期间到位的 KeyMap 值,因此我们的嵌套闭包能够捕获它。我们及时拍摄当时有效范围的快照。

我们创建的函数允许我们在每次想要检查关键代码时跳过设置 code 变量,现在我们可以使用方便、可读的函数。


使用闭包扩展语言

至此,应该相对容易看出闭包对于编写一流的 JavaScript 至关重要。让我们应用我们对闭包的了解来增强 JavaScript 的一种原生类型(惊呼!)。我们将重点放在函数对象上,让我们增强本机 Function 类型:

Function.prototype.cached = function() {
	var self = this, //"this" refers to the original function
		cache = {}; //our local, lexically scoped cache storage
	return function(args) {
		if(args in cache) return cache[args];
		return cache[args] = self(args);
	};
};
Nach dem Login kopieren

这个小宝石允许任何函数创建其自身的缓存版本。您可以看到该函数返回一个函数本身,因此可以像这样应用和使用此增强功能:

Math.sin = Math.sin.cached();
Math.sin(1) // => 0.8414709848078965
Math.sin(1) // => 0.8414709848078965 this time pulled from cache
Nach dem Login kopieren

注意发挥作用的结束技巧。我们有一个本地 cache 变量,该变量保持私有并与外界屏蔽。这将防止任何可能使我们的缓存失效的篡改。

返回的闭包可以访问外部函数的绑定,这意味着我们能够返回一个可以完全访问内部缓存以及原始函数的函数!这个小函数可以为性能带来奇迹。这个特定的扩展被设置为处理一个参数,但我很想看到您对多参数缓存函数的尝试。


野外关闭

作为额外的好处,让我们看一下闭包的一些实际用途。

jQuery

有时,著名的 jQuery $ 工厂不可用(例如 WordPress),而我们希望以通常的方式使用它。我们可以使用闭包来允许内部函数访问我们的 $ 参数绑定,而不是使用 jQuery.noConflict

(function($){
	$(document).ready(function(){
		//business as usual....
	});
})(jQuery);
Nach dem Login kopieren

骨干.js

在大型 Backbone.js 项目中,将应用程序模型设为私有,然后在主应用程序视图上公开一个公共 API 可能会更有利。使用闭包,您可以轻松实现此隐私。

(function(exports){

var Product = Backbone.Model.extend({
    urlRoot: '/products',
});

var ProductList = Backbone.Collection.extend({
    url: '/products',
    model: Product
});

var Products = new ProductList;

var ShoppingCartView = Backbone.View.extend({

    addProduct: function (product, opts) {
        return CartItems.create(product, opts);
    },

    removeProduct: function (product, opts) {
        Products.remove(product, opts);
    },

    getProduct: function (productId) {
        return Products.get(productId);
    },

    getProducts: function () {
        return Products.models;
    }
});

//export the main application view only
exports.ShoppingCart = new ShoppingCartView;

})(window);
Nach dem Login kopieren

结论

快速回顾一下我们所学到的知识:

  • 闭包只不过是一个具有作用域的函数对象。
  • 闭包因其“关闭”其内容的方式而得名。
  • 闭包在 JavaScript 的词法范围上带来了巨大的收益。
  • 闭包是 JavaScript 中实现隐私的方式。
  • 闭包能够捕获外部函数的局部变量和参数绑定。
  • JavaScript 可以通过一些闭包魔法进行强大的扩展。
  • 闭包可以与许多您喜爱的库一起使用,让它们变得更酷!

非常感谢您的阅读!随意问任何问题。现在让我们享受披萨派对吧!

Das obige ist der detaillierte Inhalt vonVerschluss von vorne nach hinten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage