JavaScript闭包

117 阅读2分钟

​1、概念

"一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)"。

这句话是是MDN中关于闭包的定,这里面解释了闭包的概念。闭包由两部分组成,函数及其执行上下文。

在JavaScript中函数可以访问它的外层函数的作用域,而且一旦函数访问了它的外层函数的作用域中定义的变量,那么就产生了闭包。

function func1() {
    let num= 18;
    let func2 = function () {
        console.log(num)
    }
    return func2
}
var f = func1();
f();
上面的例子,函数func2和它的执行上下文func1就组成了一个闭包。

2、作用

我们发明一件东西总是有它的作用,那么闭包的产生自然也有它的作用。闭包的作用就是用来解决一个问题的,这个问题就是在函数的外部访问函数内部定义的变量。

下面这个例子:

function func1() {
    let num = 18;
}
console.log(num)//结果:Uncaught ReferenceError: num is not defined

这个例子的结果是未定义,当然前提是没有在func1外部定义一个num的变量。这是因为在func1的外部无法访问func1内部定义的变量。

而闭包就是用来解决这个问题的

下面这个例子:

function func1() {
    let num= 18;
    let func2 = function () {
        return num
    }
    return func2
}

var f = func1(); console.log(f()); //结果:18 上面这个例子定义了一个函数func1,内部定义了两个变量,其中func2是一个函数,函数的返回值就是了一个变量num。然后讲func2作为func1的返回值。 这样我们在外部就能读取func1内部的变量num了。

此外,闭包还有另外一个用处,这就是让这些变量的值始终保持在内存中。 下面例子:

function func1() {
    let num = 0;
    add = function () {
        num += 1
    }
    function func2() {
        return num
    }
    return func2;
}
let func = func1();
console.log(func()); // 999
add();
console.log(func()); // 1000

上面的代码中,func2一共运行了两次,第一次的值是0,第二次的值是1。这证明了,函数func1中的局部变量num一直保存在内存中,并没有在func1调用后被自动清除。 原因就在于func1是func2的父函数,而func2被赋给了一个全局变量func,这导致func2始终在内存中,而func2的存在依赖于func1,因此func1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

3、注意事项

①闭包使用会在函数外部改变函数内部的变量的值,有可能在使用时闭包变量的值已经不是最开始的那个值。

②内存泄露问题