深入理解闭包

一,闭包定义

1. 闭包是指可以访问其所在作用域的函数

  那这样说来,需要通过作用域链查找变量的函数就是闭包

1 //按照定义一的说法,需要通过作用域链在全局环境中查找变量n的函数foo()就是闭包
2 var n = 0;
3 function foo() {
4     console.log(n)//0
5 }
6 foo();

2. 闭包是指有权访问另一个函数作用域中的变量的函数

  那这样说来,访问上层函数的作用域的内层函数就是闭包

1 nction foo(){
2     var a = 2;
3     function bar(){
4         console.log(a); // 2
5     }
6     bar();
7 }
8 foo();

3. 闭包是指在函数声明时的作用域以外的地方被调用的函数

  在函数声明时的作用域以外的地方调用函数,需要通过将该函数作为返回值或者作为参数被传递

  3.1 返回值:

1 //按照定义三的说法,在foo()函数的作用域中声明,在全局环境的作用域中被调用的bar()函数是闭包
2 function foo(){
3     var a = 2;
4     function bar(){
5         console.log(a); //2
6     }
7     return bar;
8 }
9 foo()();

可简写为如下形式:

1 function foo(){
2     var a = 2;
3     return function(){
4         console.log(a);//2
5     }
6 }
7 foo()();

  3.2 参数:

 1 //按照定义三的说法,在foo()函数的作用域中声明,在bar()函数的作用域中被调用的baz()函数是闭包
 2 function foo(){
 3     var a = 2;
 4     function baz(){
 5         console.log(a); //2
 6     }
 7     bar(baz);
 8 }
 9 function bar(fn){
10     fn();
11 }

二,立即执行函数IIFE(Imdiately Invoked Function Expression)

IIFE是不是闭包呢?

  foo()函数在全局作用域定义,也在全局作用域被立即调用,如果按照定义一的说法来说,它是闭包。如果按照定义二和定义三的说法,它又不是闭包

1 var a = 2;
2 (function foo(){
3     console.log(a);//2
4 })();

还有一个更重要的原因是,在requireJS出现之前,实现模块化编程主要通过IIFE,而在IIFE中常见的操作就是通过window.fn = fn来暴露接口,而这个fn就是闭包,而IIFE只是一个包含闭包的函数调用

1 (function(){
2     var a = 0;
3     function fn(){
4         console.log(a); 
5     }
6     window.fn = fn;
7 })()
8 fn();

 

严格来说,闭包需要满足三个条件:【1】访问所在作用域;【2】函数嵌套;【3】在所在作用域外被调用

  有些人觉得只满足条件1就可以,所以IIFE是闭包;有些人觉得满足条件1和2才可以,所以被嵌套的函数才是闭包;有些人觉得3个条件都满足才可以,所以在作用域以外的地方被调用的函数才是闭包

posted @ 2020-03-02 10:44  大前端小菜鸟  阅读(551)  评论(0编辑  收藏  举报