JS中的闭包回顾

在弄明白函数闭包前,先要弄清楚函数执行时的上下文环境。

 1console.log(fn);
 2var fn = function(){    //函数表达未
 3    return 55;
 4}
 5//打印 undefined
 6
 7console.log(fn);
 8function fn(){      //函数声明
 9    return 55;
10}
11//打印
12/*
13ƒ fn(){
14        return 55;
15    }
16*/    

在全局环境下,由于有变量提升这个机制在,所以在执行上下文环境中,数据体现的不尽相同:

  • 变量、函数表达示 ———— 变量声明,默认赋值为 undefined
  • this ———— 赋值
  • 函数声明 ———— 赋值

而在函数体环境中,函数体内的arguments变量和函数的参数都已经被赋值,函数每次调用,都会创建一个新的上下文环境,因为不同的调用可能会有不同的参数。

1function fn(x){
2    console.log(arguments);     // [10]
3    console.log(x);             // 10
4}
5fn(10)

但是注意在函数定义(不是调用)的时候,就已经确定了函数体内部自由变量的作用域。

1var x = 22;
2function fn(){
3    console.log(x);     //x是自由变量,在函数fn创建时就确定了x要取值的作用域
4}
5function fn2(f){
6    var x = 50;
7    f();       //打印22,而不是50
8}
9fn2(fn)

给执行上下文环境下个通俗的定义:在执行代码前,把将要用到的所有变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。

关于作用域,需要知道JS中没有块级作用域,此外还需要注意JS除了全局作用域外,只有函数可以创建局部作用域

作用域的概念比较抽象,可以理解为“地盘”,看下图:

上图所示,全局代码和fn、bar两个函数都会形成自己的作用域。而且,作用域有上下级关系,上下级关系的确定就看函数是在哪个作用域下确定的。例如,fn作用哉下创建了bar函数,那"fn作用域"就是"bar作用域"的上级。

作用域最大的作用就是隔离变量,不同作用域下同名变量不会有冲突。

这里再补充个自由变量的概念:在某个作用域中使用的变量X,却没有在该作用域中声明(换句话说就是变量X是在其他作用域中声明的),对于该作用域来说,这个变量X就是自由变量。那么这个自由变量X的取值又该怎么取呢?记住:要到创建这个函数的作用域中去取值,举例如下。

 1var x = 10;
 2function fn1(){
 3    console.log(x)
 4}
 5function fn2(f){
 6    var b = 20;
 7    (function(){
 8        f();    //打印10,而非20
 9    })()
10}
11fn2(fn1)

了解上下文环境和作用域,就可以比较顺畅的理解闭包了。闭包通常有两个应用场景:函数作为返回值、函数作为参数传递。

1、函数作为返回值:

 1function fn(){
 2    var max = 10;
 3    return function bar(x){
 4        if(x>max){
 5            console.log(x);     //20
 6        }
 7    }
 8}
 9var f1 = fn();
10f1(20)

上例中,闭包函数bar就是作为返回值。当执行到f1(20)时,在闭包函数bar中max作为自由变量是跨域取值的,还记得怎么跨域取值么?要到创建这个函数的作用域中去取

2、函数作为参数传递

 1var max = 10,
 2    fn = function(x){
 3        if(x > max){
 4            console.log(x);
 5        }
 6    };
 7
 8(function(f){
 9    var max = 100;
10    f(15);      //15
11})(fn);

上例中,函数fn就是作为参数传递到自执行匿名函数中去的,在执行f(15)时,作为参数传递进去的fn函数中的自由变量max取的值是10而非100,原因也是在于:自由变量的取值是要到创建这个自由变量所在函数的作用中去取的

原文发布于微信公众号 - 前端小二(frontendxiao2)

原文发表时间:2018-12-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券