JavaScript的闭包

一、前言

在学习了作用域之后,我们知道函数的AO不一定会被释放,那么利用这个特性,闭包(closure)应运而生。

二、闭包原理

函数嵌套函数,函数的AO通过作用域链相互连接起来,使得函数体内的变量都可以保存在函数的AO中,于是外部环境就能利用函数作用域内的变量,这样的特性称为“闭包”。

我们看一下代码:

function outer() {
    var scope = 'outer';
    function inner() {
        return scope;
    }
    return inner;
}
var fn = outer();
console.log(fn()); // 'outer'

解析:在inner的作用域链中拷贝着其父级函数outer的作用域链,因此当函数outer执行完成之后,抛出的函数inner的作用域链中依然有outer的作用域链,产生一个闭包,这样就可以在全局环境下使用outer中的变量了。

三、闭包的应用

1. 实现公有变量

// 一个累加器
function add() {
    var count = 0;
    function addAction() {
        count++;
        console.log(count);
    }
    return addAction;
}
var myAdd = add();
myAdd(); // 1
myAdd(); // 2
myAdd(); // 3

2. 缓存存储结构

function add2() {
    var count2 = 0;
    function addAction2() {
        count2++;
        return count2;
    }
    function clearAction() {
        count2 = 0;
        return count2;
    }
    return [addAction2, clearAction];
}
var myAdd2 = add2();
console.log(myAdd2[0]()); // 1
console.log(myAdd2[0]()); // 2
console.log(myAdd2[0]()); // 3
console.log(myAdd2[0]()); // 4
// 清除一下
console.log(myAdd2[1]()); // 0
console.log(myAdd2[0]()); // 1
console.log(myAdd2[0]()); // 2
console.log(myAdd2[0]()); // 3

3. 封装功能(实现属性的私有化,避免变量公有的污染)

function counter() {
    var count3 = 0;
    var adder = {
        addAction3: function() {
            count3++;
            console.log(count3);
        },
        clearAction: function() {
            count3 = 0;
            console.log(count3);
        }
    }
    return adder;
}
var myCounter = counter();
myCounter.addAction3(); // 1
myCounter.addAction3(); // 2
myCounter.addAction3(); // 3
myCounter.clearAction(); // 0
myCounter.addAction3(); // 1
myCounter.addAction3(); // 2

四、闭包的危险

1. 造成原有的AO不释放,产生内存泄漏(memory leak),影响内存消耗,进而影响性能。

2. 如果公有变量,那么是有可能会污染全局变量的。

五、本节思维导图

posted @ 2019-06-17 11:50  见嘉于世  阅读(0)  评论(0编辑  收藏  举报  来源