最终像专业人士一样理解 JavaScript 闭包
通过深入研究高级概念之一:闭包,简短的指南可以帮助您更好地理解 JavaScript 代码的工作和执行方式。
根据Mozilla 开发者网络(MDN) 的说法,“闭包是将一个函数与其周围状态(词法环境)的引用捆绑在一起(封闭)的组合。”简而言之,这意味着另一个函数内的函数可以访问外部(父)函数的变量。
为了更好地理解闭包,请查看范围及其执行上下文。
这是一个简单的代码片段:
**var hello = "Hello";**
**function sayHelloWorld() {
var world = "World";
function wish() {
var year = "2021";
console.log(hello + " " + world + " "+ year);
}
wish();
}
sayHelloWorld();**
这是此代码的执行上下文:
(尼米莎·慕克吉,CC BY-SA 4.0)
每次创建函数时(在函数创建时),都会创建闭包。每个闭包都有三个作用域:
-
本地范围(自身范围)
-
外部函数作用域
-
全局范围
我将稍微修改上面的代码来演示闭包:
**var hello = "Hello";**
**var sayHelloWorld = function() {
var world = "World";
function wish() {
var year = "2021";
console.log(hello + " " + world + " "+ year);
}
return wish;
}
var callFunc = sayHelloWorld();
callFunc();**
内部函数wish()在执行之前就从外部函数返回了。这是因为 JavaScript 中的函数构成了闭包。
-
当sayHelloWorld运行时, callFunc保存对函数wish 的引用
-
wish维护对变量world所在的周围(词汇)环境的引用。
私有变量和方法
JavaScript 本身不支持创建私有变量和方法。闭包的一个常见且实际的用途是模拟私有变量和方法,并允许数据隐私。在闭包作用域内定义的方法具有特权。
此代码片段捕获了 JavaScript 中闭包的常见编写和使用方式:
**var resourceRecord = function(myName, myAddress) {
var resourceName = myName;
var resourceAddress = myAddress;
var accessRight = "HR";
return {
changeName: function(updateName, privilege) {
*//only HR can change the name*
if(privilege === accessRight ) {
resourceName = updateName;
return true;
} else {
return false;
}
},
changeAddress: function(newAddress) {
*//any associate can change the address*
resourceAddress = newAddress;
},
showResourceDetail: function() {
console.log ("Name:" + resourceName + " ; Address:" + resourceAddress);
}
}
}
*//Create first record*
var resourceRecord1 = resourceRecord("Perry","Office");
*//Create second record*
var resourceRecord2 = resourceRecord("Emma","Office");
*//Change the address on the first record*
resourceRecord1.changeAddress("Home");
resourceRecord1.changeName("Perry Berry", "Associate"); *//Output is false as only an HR can change the name*
resourceRecord2.changeName("Emma Freeman", "HR"); *//Output is true as HR changes the name*
resourceRecord1.showResourceDetail(); *//Output - Name:Perry ; Address:Home*
resourceRecord2.showResourceDetail(); *//Output - Name:Emma Freeman ; Address:Office***
资源记录(resourceRecord1和resourceRecord2)彼此独立。每个闭包都通过其自身的闭包引用不同版本的resourceName和resourceAddress变量。您还可以针对私有变量的处理方式应用特定规则——我添加了一项检查,用于检查谁可以修改resourceName。
使用闭包
理解闭包很重要,因为它可以让我们更深入地了解变量和函数之间的关系以及 JavaScript 代码的工作和执行方式。
学习 Javascript 的其他资源:
参考网站:https://opensource.com/article/21/2/javascript-closures
鏂囩珷鏉ユ簮锛�https://dev.to/bricourse/finally-understanding-javascript-closures-like-the-pros-3pgd