翻译:疯狂的技术宅
https://medium.freecodecamp.o…
本文首发微信公众号:前端先锋
欢迎关注,每天都给你推送新鲜的前端技术文章
闭包是函数创建时作用域内所有变量的集合。要使用闭包,需要在另一个函数中创建一个函数,这种函数被称为嵌套函数。内部函数可以访问外部函数作用域中的变量(依靠 闭包 可以访问外部函数作用域),即使在返回外部函数之后也是如此。每次创建嵌套函数时都会创建闭包。
在继续了解闭包之前,首先了解一下 JavaScript 中的作用域链。
通常,有两种类型的作用域:
- 全局作用域
- 局部作用域
在 JavaScript 中,函数内部的变量在外部是不可见的。但是在块内的变量(if 或 while 之类)是可见的。
因此,JavaScript 有函数作用域。没有块作用域。
var a = 10;
function app(){
var b = 2;
console.log(a); // 10
console.log(b); // 2
}
console.log(b); // ReferenceError: b is not defined
app();
正像我们已知的那样,a 是一个全局变量并且 b 是一个局部变量,它是 app 函数 独有的。
我们无法从局部作用域之外获取局部变量的值。
使用嵌套函数 —— 函数内部的函数
var a = 10;
function app(){
var b = 2;
var d = 3;
function add(){var c = a + b;}
return add;
}
var x = app();
console.dir(x);
在这里 app 是父函数,add 函数是子函数。
- 代码中没有用 console.log 而是用了console.dir 来输出指定 JavaScript 对象的所有属性,这有助于开发人员获取对象的属性
- 变量 x 被分配给 app 函数,app 函数返回 add 函数。因此我们可以看到 add 函数的所有对象属性。
如果在浏览器中查看控制台,可以在 Scopes 数组中看到 Closure 对象。
由于内部 函数 add访问外部函数变量b 和 d,因此这 2 个变量将被添加到 Closure 对象中以供引用。
让我们看看下一个例子:
var a = 10;
var startFunc;
function app(){
var b = 2;
function add(){
var c = a + b;
console.log(c);
}
startFunc = add();}
app(); // 调用 app 函数
startFunc; // 上面调用的 app 函数会将 add 函数赋值给 startFunc 并输出 c 的值
- 一个名为 startFunc 的全局函数被分配给 add 函数,该函数是 app 函数的子函数。
- 这只有在调用 app 函数后才有可能,否则 startFunc 将作为全局变量而不被分配任何值
在 JavaScript 中使用闭包
很多人在编码时会用到闭包,但是不明白用它的原因。JavaScript 没有像其他面向对象语言一样的访问修饰符,例如 private,public,protected。不过我们可以利用函数来保护命名空间免受外部代码使用的影响。
特别是在函数中,立即执行函数表达式(IIFE)是在声明之后会立即执行的函数表达式。在声明函数之后,你不需要去调用该函数。
IIFE 的语法定义是:
(function(){// 函数内部的变量和作用域})();
举个例子:
var studnetEnrollment = (function () {
// 私有变量,任何人都无法改变
// 除了下面声明的函数
var count = 0;
var prefix = "S";
// 返回一个命名函数表达式
function innerFunc() {
count = count + 1;
return prefix + count;
};
return innerFunc;
})();
var x = studnetEnrollment(); // S1
console.log(x);
var y = studnetEnrollment(); // S2
console.log(y);
count 和 prefix 是两个私有变量,任何人都无法进行更改,只能访问内部函数(即代码中的 innerFunc)。只有名为闭包的功能才能对此进行访问。
- 第一次调用 studentEnrollment 函数时,函数内的 count 变量由 innerFunc 函数递增加 1。
- 第二次,增加上一个计数值,即 1 增加到 2
- Closure 功能可以实现这些功能。
结论
闭包是外部函数中的变量集合,它提供对内部函数作用域的访问以保护全局命名空间。
闭包使开发人员能够编写像面向对象语言那样的干净代码,这些代码不会混淆全局和局部变量的名称。
编码快乐 …… !!!!!
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 12 个令人惊叹的 CSS 实验项目
- 必须要会的 50 个 React 面试题
- 世界顶级公司的前端面试都问些什么
- 11 个最好的 JavaScript 动态效果库
- CSS Flexbox 可视化手册
- 从设计者的角度看 React
- 过节很无聊?还是用 JavaScript 写一个脑力小游戏吧!
- CSS 粘性定位是怎样工作的
- 一步步教你用 HTML5 SVG 实现动画效果
- 程序员 30 岁前月薪达不到 30K,该何去何从
- 14 个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把 HTML 转成 PDF 的 4 个方案及实现