JavaScript 閉包實踐
在《JavaScript 如此受歡迎的 4 個原因》中,我提到了一些高級 JavaScript 概念。在本文中,我將深入探討其中的一個概念: 閉包 。
根據 Mozilla 開發者網路(MDN),「閉包是將一個函數和對其周圍的狀態(詞法環境)的引用捆綁在一起(封閉)的組合。」簡而言之,這意味著在一個函數內部的函數可以訪問其外部(父)函數的變數。
為了更好地理解閉包,可以看看作用域及其執行上下文。
下面是一個簡單的代碼片段:
var hello = "Hello";
function sayHelloWorld() {
var world = "World";
function wish() {
var year = "2021";
console.log(hello + " " + world + " "+ year);
}
wish();
}
sayHelloWorld();
下面是這段代碼的執行上下文:
![JS 代碼的執行上下文](/data/attachment/album/202102/21/163151d6tma7k3pp2lgz43.png "Execution context for JS code")
每次創建函數時(在函數創建階段)都會創建閉包。每個閉包有三個作用域。
- 本地作用域(自己的作用域)
- 外部函數範圍
- 全局範圍
我稍微修改一下上面的代碼來演示一下閉包:
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 選題:lujun9972 譯者:wxy 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive