前言
网上有很多关于闭包的描述,但是众说纷纭,让人看得云里雾里。今天,我请来了几位有声望的大佬(小"黄"书、红宝书、javascript权威指南、官方)来为闭包的身份做一下澄清,希望各位家人们以后不要再污了闭包的清白。
一起来找闭包
1.标准闭包
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
长这个样子的闭包是我们最喜欢看到的,用一句话来说就是“长得很‘标致’”,大家一看就知道这是个闭包。
2.下面是闭包吗?
function foo(){
let a=1;
function inner(){
alert(a);
debugger;
}
}
foo();
debugger;
长得像个闭包!
3.下面是闭包吗?
function foo(){
let a=1;
function inner(){
alert(a);
debugger;
}
inner();
}
foo();
debugger;
闭包:没化妆就不认识了老娘了?
4.下面是闭包吗?
function foo(){
let a=1;
function inner(){
let b=1;
debugger;
}
inner();
}
foo();
debugger;
被夺舍了,空有其形,却没有闭包的灵魂。
5.自执行函数是闭包吗?
let a=1;
(function foo(){
a++;
debugger;
})();
debugger;
不是闭包
6.自执行函数加个滤镜?
let a=1;
(function foo(a){
a++;
debugger;
})(a);
debugger;
不是闭包
7.这种呢?
(function foo(){
let a=1;
function inner(){
a++;
debugger;
}
inner();
})();
debugger;
闭包本包
8.下面是闭包吗
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
var a=i;
debugger;
}, 1000);
}
不是闭包
9.下面是闭包吗
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
var a=i;
debugger;
}, 1000);
}
不是闭包
10.下面是闭包吗?
function outer() {
var a=1;
function inner() {
eval('');
debugger;
}
inner();
}
outer();
你没看错,这是一个闭包
11.下面是闭包吗?
function outer() {
var a=1;
function inner() {
window.eval('');
debugger;
}
inner();
}
outer();
当eval通过window执行时,其上级作用域为全局作用域,不会访问outer函数下a变量。
闭包定义
1.小"黄"书(你不知道的JavaScript): 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行.
2.红宝书(JavaScript高级程序设计): 闭包是指有权访问另一个 函数作用域中的变量的函数
3.javascript权威指南:函数对象可以通过作用域链相互关联起来,函数体内部变量可以保存在函数作用域内,这就是闭包。
4.官方解释:「闭包」,是指拥有多个变量和绑定了这些变量的环境的 表达式(通常是一个函数),因而这些变量也是该表达式 的一部分。
闭包三条件:
1. 外层函数包裹内层函数
2. 内层函数引用外层函数的变量
3. 外层函数返回内层函数
有些人觉得只满足条件1就可以,所以IIFE是闭包;有些人觉得满足条件1和2才可以,所以被嵌套的函数才是闭包;有些人觉得3个条件都满足才可以,所以在作用域以外的地方被调用的函数才是闭包.
总结
就个人而言,我觉得满足1,2两个条件就是闭包,红宝书中对于闭包的定义要更加通俗易懂。另外强烈推荐大家看这边文章,并不是所有的闭包,浏览器都不会清除他所访问变量的内存。点击这儿!
参考文章:
【1】.www.cnblogs.com/rubylouvre/…
【2】.www.ruanyifeng.com/blog/2009/0…