那些年,我们一起学过的闭包

140 阅读3分钟

前言

网上有很多关于闭包的描述,但是众说纷纭,让人看得云里雾里。今天,我请来了几位有声望的大佬(小"黄"书、红宝书、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;

closure1.png

长得像个闭包!

3.下面是闭包吗?

function foo(){
    let a=1;
    function inner(){
      alert(a);
      debugger;
    }
    inner();
}
foo();
debugger;

closure2.png

闭包:没化妆就不认识了老娘了?

4.下面是闭包吗?

function foo(){
    let a=1;
    function inner(){
      let b=1;
      debugger;
    }
    inner();
}
foo();
debugger;

closure3.png

被夺舍了,空有其形,却没有闭包的灵魂。

5.自执行函数是闭包吗?

let a=1;
(function foo(){
  a++;
  debugger;
})();
debugger;

image.png

不是闭包

6.自执行函数加个滤镜?

let a=1;
(function foo(a){
  a++;
  debugger;
})(a);
debugger;

image.png

不是闭包

7.这种呢?

(function foo(){
  let a=1;
  function inner(){
    a++;
    debugger;
  }
  inner();
})();
debugger;

image.png

闭包本包

8.下面是闭包吗

for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    var a=i;
    debugger;
  }, 1000);
}

image.png

不是闭包

9.下面是闭包吗

for (let i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    var a=i;
    debugger;
  }, 1000);
}

image.png

不是闭包

10.下面是闭包吗?

function outer() {
    var a=1;

    function inner() {
        eval('');
        debugger;
    }
    inner();
}

outer();

image.png

你没看错,这是一个闭包

11.下面是闭包吗?

function outer() {
    var a=1;

    function inner() {
        window.eval('');
        debugger;
    }
    inner();
}

outer();

image.png

当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…

【3】.juejin.cn/post/684490…

【4】.zhuanlan.zhihu.com/p/22486908

【5】.www.gracecode.com/posts/2385.…