《你不知道的JS(上卷)》作用域闭包
Posted lalal
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《你不知道的JS(上卷)》作用域闭包相关的知识,希望对你有一定的参考价值。
五、作用域闭包:
? 闭包不是神奇的魔法,它只是遵循我们前几章一直介绍的 词法作用域书写代码的自然结果。
? 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
一)、回调函数与闭包:
- 回调函数,将一个函数的引用作为参数传递给另一个函数。
function wait(meesage) {
setTimeout(function timer() {
console.log(meesage);
}, 1000);
}
wait("Hello, closure!")
? 无论何时何地,如果将函数(访问他们各自的词法作用域)当作第一级的值类型并到处传递,就可以看到闭包的存在。在定时器、事件监听器、Ajax请求、跨窗口通信等异步或同步任务中,只要使用了回调函数,实际上就是在使用闭包。
二)、循环与闭包:
// 使用var
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000)
} // 6 6 6 6 6
// 使用let
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000)
} // 1 2 3 4 5
? 比较上面两段代码与输出结果。发现使用var在循环中声明变量不能达到我们想要的效果。这是因为尽管每次循环都定义了一个新的函数,但是对于这些函数,是共享同一个作用域的,因此i也是相同的。而使用let,会在每次迭代时都创建一个新的作用域。并且使用let会让i这个变量在每次迭代都会声明,且会使用上一个迭代结束时的值来初始化这个变量。
三)、模块模式:
? 在许多面向对象语言(如Java)中,都支持将方法声明为私有,即只能被同一个类中的方法调用。在javascript中并没有这种原生支持。我们可以使用闭包来模拟私有方法,这种方式也被称作 模块模式。
? 这种方式不仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱代码的公共接口部分。
var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log(something);
}
function doAnother() {
console.log(another.join("!"));
}
return {
doSomething: doSomething,
doAnother: doAnother
}
})();
foo.doSomething(); // cool
foo.doAnother(); // 1!2!3
ES6中的模块机制:
? ES6中为模块增加了一级语法支持。但通过模块系统进行加载时,ES
6会将文件当作独立的模块来处理。每个模块都可以导入其他模块或特定的API成员,同样也可以到处自己的API成员。
- import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上。
- module会将整个模块的API导入并绑定到一个变量上。
- export会将当前模块的一个标识符(变量、函数)导出为公共API。
四)、小结:
- 闭包虽然随处可见,但是不要滥用。使用闭包在处理速度和内存消耗方面对脚本性能具有负面影响。
- 理解闭包的关键还是前几章讲述的词法作用域,因此不能跳过前几章!
以上是关于《你不知道的JS(上卷)》作用域闭包的主要内容,如果未能解决你的问题,请参考以下文章