mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-10 00:00:29 +08:00
TSL
This commit is contained in:
parent
34f1cba859
commit
92da32c658
@ -1,144 +0,0 @@
|
|||||||
[#]: collector: (lujun9972)
|
|
||||||
[#]: translator: (wxy)
|
|
||||||
[#]: reviewer: ( )
|
|
||||||
[#]: publisher: ( )
|
|
||||||
[#]: url: ( )
|
|
||||||
[#]: subject: (A practical guide to JavaScript closures)
|
|
||||||
[#]: via: (https://opensource.com/article/21/2/javascript-closures)
|
|
||||||
[#]: author: (Nimisha Mukherjee https://opensource.com/users/nimisha)
|
|
||||||
|
|
||||||
A practical guide to JavaScript closures
|
|
||||||
======
|
|
||||||
Get a better understanding of how JavaScript code works and executes by
|
|
||||||
diving into one of the advanced concept: closures.
|
|
||||||
![Woman programming][1]
|
|
||||||
|
|
||||||
In [_4 reasons why JavaScript is so popular_][2], I touched on a few advanced JavaScript concepts. In this article, I will dive into one of them: closures.
|
|
||||||
|
|
||||||
According to [Mozilla Developer Network][3] (MDN), "A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment)." Simplified, this means that a function inside another function can access the variables from the outer (parent) function.
|
|
||||||
|
|
||||||
To better understand closures, take a look at scopes and their execution context.
|
|
||||||
|
|
||||||
Here is a simple code snippet:
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
var hello = "Hello";
|
|
||||||
|
|
||||||
function sayHelloWorld() {
|
|
||||||
var world = "World";
|
|
||||||
function wish() {
|
|
||||||
var year = "2021";
|
|
||||||
console.log(hello + " " + world + " "+ year);
|
|
||||||
}
|
|
||||||
wish();
|
|
||||||
}
|
|
||||||
sayHelloWorld();
|
|
||||||
```
|
|
||||||
|
|
||||||
Here's the execution context for this code:
|
|
||||||
|
|
||||||
![Execution context for JS code][4]
|
|
||||||
|
|
||||||
(Nimisha Mukherjee, [CC BY-SA 4.0][5])
|
|
||||||
|
|
||||||
Closures are created every time a function is created (at function-creation time). Every closure has three scopes:
|
|
||||||
|
|
||||||
* Local scope (own scope)
|
|
||||||
* Outer functions scope
|
|
||||||
* Global scope
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
I'll modify the above code slightly to demonstrate closure:
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
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();
|
|
||||||
```
|
|
||||||
|
|
||||||
The inner function `wish()` is returned from the outer function before it's executed. This happens because functions in JavaScript form **closures**.
|
|
||||||
|
|
||||||
* `callFunc` holds a reference to the function `wish` when `sayHelloWorld` runs
|
|
||||||
* `wish` maintains a reference to its surrounding (lexical) environment where the variable `world` exists.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Private variables and methods
|
|
||||||
|
|
||||||
Natively, JavaScript does not support the creation of private variables and methods. A common and practical use of closure is to emulate private variables and methods and allow data privacy. Methods defined within the closure scope are privileged.
|
|
||||||
|
|
||||||
This code snippet captures how closures are commonly written and used in 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
|
|
||||||
```
|
|
||||||
|
|
||||||
The resource records (`resourceRecord1` and `resourceRecord2`) are independent of one another. Each closure references a different version of the `resourceName` and `resourceAddress` variable through its own closure. You can also apply specific rules to how private variables need to be handled—I added a check on who can modify `resourceName`.
|
|
||||||
|
|
||||||
### Use closures
|
|
||||||
|
|
||||||
Understanding closure is important, as it enables deeper knowledge of how variables and functions relate to one another and how JavaScript code works and executes.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
via: https://opensource.com/article/21/2/javascript-closures
|
|
||||||
|
|
||||||
作者:[Nimisha Mukherjee][a]
|
|
||||||
选题:[lujun9972][b]
|
|
||||||
译者:[译者ID](https://github.com/译者ID)
|
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
|
||||||
|
|
||||||
[a]: https://opensource.com/users/nimisha
|
|
||||||
[b]: https://github.com/lujun9972
|
|
||||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop-music-headphones.png?itok=EQZ2WKzy (Woman programming)
|
|
||||||
[2]: https://opensource.com/article/20/11/javascript-popular
|
|
||||||
[3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
|
|
||||||
[4]: https://opensource.com/sites/default/files/uploads/execution-context.png (Execution context for JS code)
|
|
||||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
|
@ -0,0 +1,136 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (wxy)
|
||||||
|
[#]: reviewer: ( )
|
||||||
|
[#]: publisher: ( )
|
||||||
|
[#]: url: ( )
|
||||||
|
[#]: subject: (A practical guide to JavaScript closures)
|
||||||
|
[#]: via: (https://opensource.com/article/21/2/javascript-closures)
|
||||||
|
[#]: author: (Nimisha Mukherjee https://opensource.com/users/nimisha)
|
||||||
|
|
||||||
|
JavaScript 闭包实践
|
||||||
|
======
|
||||||
|
|
||||||
|
> 通过深入了解 JavaScript 的高级概念之一:闭包,更好地理解 JavaScript 代码的工作和执行方式。
|
||||||
|
|
||||||
|
![女性编程][1]
|
||||||
|
|
||||||
|
在《[JavaScript 如此受欢迎的 4 个原因][2]》中,我提到了一些高级 JavaScript 概念。在本文中,我将深入探讨其中的一个概念:<ruby>闭包<rt>closure</rt></ruby>。
|
||||||
|
|
||||||
|
根据 [Mozilla 开发者网络][3](MDN),“闭包是将一个函数和对其周围的状态(词法环境)的引用捆绑在一起(封闭)的组合。”简而言之,这意味着在一个函数内部的函数可以访问其外部(父)函数的变量。
|
||||||
|
|
||||||
|
为了更好地理解闭包,可以看看作用域及其执行上下文。
|
||||||
|
|
||||||
|
下面是一个简单的代码片段:
|
||||||
|
|
||||||
|
```
|
||||||
|
var hello = "Hello";
|
||||||
|
|
||||||
|
function sayHelloWorld() {
|
||||||
|
var world = "World";
|
||||||
|
function wish() {
|
||||||
|
var year = "2021";
|
||||||
|
console.log(hello + " " + world + " "+ year);
|
||||||
|
}
|
||||||
|
wish();
|
||||||
|
}
|
||||||
|
sayHelloWorld();
|
||||||
|
```
|
||||||
|
|
||||||
|
下面是这段代码的执行上下文:
|
||||||
|
|
||||||
|
![JS 代码的执行上下文][4]
|
||||||
|
|
||||||
|
每次创建函数时(在函数创建阶段)都会创建闭包。每个闭包有三个作用域。
|
||||||
|
|
||||||
|
* 本地作用域(自己的作用域)
|
||||||
|
* 外部函数范围
|
||||||
|
* 全局范围
|
||||||
|
|
||||||
|
我稍微修改一下上面的代码来演示一下闭包:
|
||||||
|
|
||||||
|
```
|
||||||
|
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 代码如何工作和执行。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/21/2/javascript-closures
|
||||||
|
|
||||||
|
作者:[Nimisha Mukherjee][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[校对者ID](https://github.com/校对者ID)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/nimisha
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop-music-headphones.png?itok=EQZ2WKzy (Woman programming)
|
||||||
|
[2]: https://linux.cn/article-12830-1.html
|
||||||
|
[3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
|
||||||
|
[4]: https://opensource.com/sites/default/files/uploads/execution-context.png (Execution context for JS code)
|
||||||
|
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
Loading…
Reference in New Issue
Block a user