js闭包学习及代码演示

参考《JavaScript高级程序设计》

预备

执行环境定义了变量或函数有权访问的其他数据

每个函数都有自己的执行环境

每个执行环境都有一个与之关联的变量对象

当代码在一个环境中执行时,会创建变量对象的一个作用域链( scope chain)。

作用域链的用途:保证对执行环境有权访问的所有变量和函数的有序访问。
 

闭包

有权访问另一个函数作用域中的变量的函数。

创建闭包的常见方式:在一个函数内部创建另一个函数

区别

在函数中访问一个变量时,就会从作用域链中搜索具有相应名字的变量。

一般来讲,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
但是在另一个函数内部定义的函数(闭包)会将包含函数(即外部函数)的活动对象添加到它的作用域链中。

实验代码

/**
   * 返回根据属性propertyName对两个对象的比较方法
*/
function createComparisonFunction(propertyName) {
    let globalVal = "ok";
    return function(object1, object2) {
        console.log("createComparisonFunction作用域中的globalVal是, ", globalVal);
        let value1 = object1[propertyName];
        let value2 = object2[propertyName];
        if (value1 < value2){
            return -1;
        } else if (value1 > value2){
            return 1;
        } else {
            return 0;
        }
    };
}
/**
* 测试闭包会将包含函数的活动对象添加到它的作用域链中
*/
function test1(){
    let p1 = {"age": 10};
    let p2 = {"age": 11};
    let cmpFunc = createComparisonFunction("age");
    console.log("p1和p2的比较结果是", cmpFunc(p1, p2));
    //注意下面第二次执行cmpFunc的时候依然可以获取globalVal的值
    console.log("p2和p1的比较结果是", cmpFunc(p2, p1));
    //解除引用,释放内存
    comFunc = null;
}
test1();
//输出如下
createComparisonFunction作用域中的globalVal是,  ok
p1和p2的比较结果是 -1
createComparisonFunction作用域中的globalVal是,  ok
p2和p1的比较结果是 1

特殊

闭包只能取得包含函数中任何变量的最后一个值

别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。

代码:注意for循环中使用了var

/**
   * 返回函数数组
*/
function createArrayByFunctions(){
    let result = [];
    for(var i = 0; i < 10; i++) {
        result[i] = function() {
            return i;
        };
    }
    return result;
}
/**
   * 测试函数数组的函数值
*/
function test2(){
    let arr = createArrayByFunctions();
    arr.forEach(item => {
        process.stdout.write(item()+" ")
    });
}
test2();
//输出
10 10 10 10 10 10 10 10 10 10


意外:把var换为let,结果正常

分析:let 是块级作用域,而 var 是函数作用域。使用let时每一个不同值的i都因为闭包所以保存下来。

0 1 2 3 4 5 6 7 8 9
发布了63 篇原创文章 · 获赞 18 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/liuxiang15/article/details/104720245
今日推荐