JavaScript 的闭包是什么

JavaScript 中的变量有两种:

  • 全局变量
  • 局部变量

使用 闭包 我们可以将全局变量变为局部变量。

两种变量

一个函数可以访问它内部定义的变量,比如这样:

function myFunction() {
    var a = 4;
    return a * a;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

同时函数也可以访问它外部定义的变量,比如这样:

var a = 4;
function myFunction() {
    return a * a;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

第一个例子中,a 是一个 局部变量

局部变量只能在创建它的函数内使用,其他范围(其他函数等)都访问不到它。

在第二个例子中,a 是一个 全局变量

在网页中,全局变量都属于 window 对象。

全局变量可以被当前页面的所有脚本使用或者修改。

和 Java 中相同的是: 
全局变量和局部变量即使名称相同,也是不同的变量,修改其中一个不会影响另一个。

注意,不使用关键字 var,直接创建的变量,永远是全局变量,哪怕它是在函数中创建的!

变量的生命周期

全局变量的生命周期和创建它的网页/ window 声明周期一致。

局部变量则短一些,它在函数调用(不是创建)时创建,在函数结束时被删除。

计数器的困境

假设你想要用一个变量计数,你想要让所有函数都可以使用这个计数器。

你可以使用一个全局变量,然后提供一个方法来增加它:

var counter = 0;

function add() {
    counter += 1;
}

add();
add();
add();

// 现在计数器的值是 3
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

我们想要的效果是只能通过 add() 方法增加计数器的值。

但由于 counter 是全局变量,当前页面的脚本,不使用 add() 也能修改它。

那我们就把 counter 声明为局部变量,这样所有人要使用它只能通过 add() 方法:

function add() {
    var counter = 0;
    counter += 1;
}

add();
add();
add();

// 我们想要的效果是 counter 等于 3,但它并没有这样
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

每次调用 add() 方法,它都会将 counter 设置为 1.

JavaScript 的内部函数可以解决这个问题。

JavaScript 的嵌套函数

在 JavaScript 中,所有的函数都可以访问全局变量,除此外,它们还可以访问 “上一级函数” 中声明的变量(类似 Java 内部类)。

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在上面的例子中,内部函数 plus() 可以访问父函数的 counter 变量。

现在我们有了局部变量,也有了内部函数,只要能在最外部范围访问内部函数 plus(),我们就能逃离计数器的困境了。

哦对了,我们还需要只初始化一次 counter

我们需要使用闭包。

JavaScript 的闭包

还记得自调用函数 IIFE (Immediately Invoked Function Expression)吗?它做了什么?

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// 现在 counter 的值就是 3
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上述代码,先创建了一个自调用匿名函数,这个函数在创建时就进行了自调用,完成了 counter 的初始化。

然后将函数 {return counter += 1;} 赋值给 add 变量,add 就变成了函数。

关键的部分在于:add() 方法可以访问父函数声明的 counter 变量

counter 被匿名函数的作用域保护着,我们只能通过 add() 方法修改它。

这就是闭包,它让函数可以拥有“私有”变量。

闭包就是一个函数即使在父函数关闭之后,也可以访问父函数中的变量。



本文翻译自 w3schools:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值