每天一个前端知识(45):使用立即调用的函数表达式创建局部作用域

frontend

Posted by Tiny on July 9, 2017
// 新的函数才会产生新的作用域,JavaScript的循环没有新的作用域产生。
// 测试使用的数组
var testArr = [1, 2, 3];
// @1 不使用闭包的情况下我们使用的是的引用
function generateFunc(arr) {
    var result = [];
    var n = arr.length;
    for(var i = 0; i < n; i++) {
        result[i] = function() {
            return arr[i];
        }
    }
    return result;
}
// @1 产生新的函数
var g1 = generateFunc(testArr);
// 此时的i已经变成了3
console.log(g1[0]()); // undefined
console.log(g1[1]()); // undefined
console.log(g1[2]()); // undefined
// @2 使用闭包方式一
function generateFunc1(arr) {
    var result = [];
    var n = arr.length;
    for(var i = 0; i < n; i++) {
        (function(j) {
            result[j] = function() {
                return arr[j];
            }
        })(i)
    }
    return result;
}
// @2 产生新的函数
var g2 = generateFunc1(testArr);
console.log(g2[0]()); // 1
console.log(g2[1]()); // 2
console.log(g2[2]()); // 3
// @3 使用闭包方式二
function generateFunc2(arr) {
    var result = [];
    var n = arr.length;
    for(var i = 0; i < n; i++) {
        (function() {
            var j = i; // 注意这里
            result[i] = function() {
                return arr[j];
            }
        })()
    }
    return result;
}
// @3 产生新的函数
//var g3 = generateFunc1(testArr);
var g3 = generateFunc2(testArr);
console.log(g3[0]()); // 1
console.log(g3[1]()); // 2
console.log(g3[2]()); // 3

谨记

理解绑定与赋值的区别。

闭包通过引用而不是值捕获它们的外部变量。

使用立即调用的函数表达式(IIFE)来创建局部作用域。

当心在立即调用的函数表达式中包裹代码块可能改变其行为的情形。

参考资料:https://lee134134134.github.io/page/7/