¥Closures
闭包是 JavaScript 最强大的功能之一。JavaScript 允许函数嵌套,并授予内部函数对外部函数内部定义的所有变量和函数(以及外部函数有权访问的所有其他变量和函数)的完全访问权限。
¥Closures are one of the most powerful features of JavaScript. JavaScript allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to).
但是,外部函数无法访问内部函数内部定义的变量和函数。这为内部函数的变量提供了一种封装。
¥However, the outer function does not have access to the variables and functions defined inside the inner function. This provides a sort of encapsulation for the variables of the inner function.
此外,由于内部函数可以访问外部函数的作用域,因此如果内部函数设法在外部函数的生命周期之外生存,则外部函数中定义的变量和函数的生存时间将比外部函数执行的持续时间长。 功能。当内部函数以某种方式可用于外部函数之外的任何作用域时,就会创建闭包。
¥Also, since the inner function has access to the scope of the outer function, the variables and functions defined in the outer function will live longer than the duration of the outer function execution, if the inner function manages to survive beyond the life of the outer function. A closure is created when the inner function is somehow made available to any scope outside the outer function.
js// The outer function defines a variable called "name"
const pet = function (name) {
const getName = function () {
// The inner function has access to the "name" variable of the outer function
return name;
};
return getName; // Return the inner function, thereby exposing it to outer scopes
};
const myPet = pet("Vivie");
console.log(myPet()); // "Vivie"
它可能比上面的代码复杂得多。可以返回一个包含用于操作外部函数的内部变量的方法的对象。
¥It can be much more complex than the code above. An object containing methods for manipulating the inner variables of the outer function can be returned.
jsconst createPet = function (name) {
let sex;
const pet = {
// setName(newName) is equivalent to setName: function (newName)
// in this context
setName(newName) {
name = newName;
},
getName() {
return name;
},
getSex() {
return sex;
},
setSex(newSex) {
if (
typeof newSex === "string" &&
(newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")
) {
sex = newSex;
}
},
};
return pet;
};
const pet = createPet("Vivie");
console.log(pet.getName()); // Vivie
pet.setName("Oliver");
pet.setSex("male");
console.log(pet.getSex()); // male
console.log(pet.getName()); // Oliver
在上面的代码中,外部函数的 name 变量可以被内部函数访问,并且除了通过内部函数之外没有其他方法可以访问内部变量。内部函数的内部变量充当外部参数和变量的安全存储。它们保存 "persistent" 和 "encapsulated" 数据供内部函数使用。这些函数甚至不必分配给变量或有名称。
¥In the code above, the name variable of the outer function is accessible to the inner functions, and there is no other way to access the inner variables except through the inner functions. The inner variables of the inner functions act as safe stores for the outer arguments and variables. They hold "persistent" and "encapsulated" data for the inner functions to work with. The functions do not even have to be assigned to a variable, or have a name.
jsconst getCode = (function () {
const apiCode = "0]Eal(eh&2"; // A code we do not want outsiders to be able to modify…
return function () {
return apiCode;
};
})();
console.log(getCode()); // "0]Eal(eh&2"
注意:使用闭包时有许多陷阱需要注意!
¥Note: There are a number of pitfalls to watch out for when using closures!
如果封闭函数定义了与外部作用域中的变量同名的变量,则无法再次引用外部作用域中的变量。(内部作用域变量 "overrides" 是外部作用域变量,直到程序退出内部作用域。可以将其视为 名称冲突。)
¥If an enclosed function defines a variable with the same name as a variable in the outer scope, then there is no way to refer to the variable in the outer scope again. (The inner scope variable "overrides" the outer one, until the program exits the inner scope. It can be thought of as a name conflict.)
jsconst createPet = function (name) {
// The outer function defines a variable called "name".
return {
setName(name) {
// The enclosed function also defines a variable called "name".
name = name; // How do we access the "name" defined by the outer function?
},
};
};