关于JavaScript的闭包

1、前言

闭包它在百度百科中的解释原话是这样的:闭包就是可以读取其余函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,因此闭包能够理解成定义在一个函数内部的函数。在本质上,闭包是将函数内部和函数外部链接起来的桥梁。javascript

下面来一一解读这段话。java

2、闭包是什么?

首先来直接回答这个问题:闭包是什么?闭包

答案:闭包是一个函数,什么函数呢?一个定义在函数内部的函数。例如:异步

var add = (function () {
    var counter = 0;
    return function () {
        return counter += 1;
    }
})();
复制代码

在上面的例子中,函数内部return的这个函数function () {return counter += 1;},它就是一个闭包。咱们直接把add在控制台打印出来: 函数

咱们能够看到,在这里全局定义的这个变量 add,它其实是一个函数,可是这个函数倒是在另外一个函数内部建立的,这个就是 定义在函数内部的函数

3、闭包有什么做用?

一、闭包能够访问到局部变量

即咱们要解读这句话:可以读取其余函数内部变量的函数性能

咱们知道,在JavaScript中,有全局变量和局部变量。顾名思义,全局变量它是公有的、共享的,程序内的全部函数均可以直接调用这个全局变量,即它的做用域是全局性的;而局部变量,在函数内部声明的变量,它是私有的,只在函数内部起做用,在该函数以外的地方是没法被调用的,它的做用域是局部性的。ui

function add() {
    var counter = 0;
    return counter += 1;
}
console.log(add()); // 1
console.log(add()); // 1
console.log(add()); // 1
// 本意是想输出 3, 但事与愿违,输出的都是 1 
复制代码

以上代码将没法正确输出,每次调用add()函数,计数器都会设置为1。能够将它写成闭包的形式,使counter = 0只执行一次,并返回函数表达式,而后获得咱们想要输出的结果。spa

function add() {
    var counter = 0;
    return function () {
        return counter += 1;
    }
}
var closure = add();
console.log(closure()); // 1
console.log(closure()); // 2
console.log(closure()); // 3
复制代码

闭包它能够访问函数上一层做用域的局部变量,它使得函数拥有私有变量变成可能。3d

二、闭包能够保护里面的局部变量,使它们不会随着函数的结束而销毁

百度百科里面还有这么一段话:“闭包”一词来源于如下二者的结合:要执行的代码块(因为自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(做用域)。code

这句话含有一个意思,就是在闭包内部的变量它是不会被销毁的,会一直存在内存中,而且不会受到外界的干扰。在上面的例子中counter的值就是这样受到闭包的保护,只能经过closure方法去修改。

4、闭包的应用

闭包有两个做用,一个是能够访问到局部变量,另外一个就是让这些变量的值始终保持在内存中。咱们能够用闭包来解决一个经典的问题:

for (var i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 10)
}
复制代码

由于setTimeout是个异步函数,因此会先把循环所有执行完毕,这时候i就是6 了,因此会输出一堆6。这个时候咱们就能够用闭包去解决这个问题啦:

for (var i = 1; i <= 5; i++) {
    (function(j) {
        setTimeout(function timer() {
            console.log(j);
        }, 10)
    })(i)
}
复制代码

在上面的代码中,咱们首先使用了当即执行函数将i传入函数内部,这个时候值就被固定在了参数j 上面不会改变,当下次执行timer这个闭包的时候,就可使用外部函数的变量j,从而达到目的。

固然,解决这个问题还能够用let和传入setTimeout的第三个参数,在这里就不一一展开描述了。

闭包由于会把变量保存在内存中,能够用来生成一个计时器,也就是文章开始的这个例子。

var add = (function () {
    var counter = 0;
    return function () {
        return counter += 1;
    }
})();
复制代码

5、使用闭包须要注意些什么?

一、闭包会使得函数中的变量都被保存在内存中,会增大内存的使用量,而且使用不当会容易形成内存泄漏。

由于,在JavaScript的垃圾自动回收机制中有这么一句话:从逻辑上讲,永远不能释放进入环境的变量所占用的内存,由于只要执行流进入相应的环境,就可能会用到它们。由于进入闭包的变量是有可能继续使用的,即它们不会被自动回收,这个时候须要咱们手动回收清除。

二、若是不是由于某些特殊任务而须要闭包,在没有必要的状况下,在其它函数中建立函数是不明智的,由于闭包对脚本性能具备负面影响,包括处理速度和内存消耗。

最后,推荐观看下面关于闭包的这篇文章:

developer.mozilla.org/zh-CN/docs/…

相关文章
相关标签/搜索