JavaScript函数(三)——闭包及作用域

闭包

概念

只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁

例子

function outer(){
    var localVal = 30;
    return localVal;
}

outer();//30

function outer(){
    var localVal = 30;
    return function() {
        return localVal;
    }
}

var func = outer();
func();//30

作用:比如在一个函数中嵌套一个函数,通过闭包可以让嵌套函数访问到包裹它的函数的局部变量。

封装

(function(){
    var _userId = 123;
    var _typeId = 'item';
    var export = {};
    
    function converter(userId){
        return + userId;
    }
    
    export.getUserId = function(){
        return converter(_userId);
    }
    
    export.getTypeId = function(){
        return _typeId;
    }
    window.export = export;
})();

export.getUserId();//123
export.getTypeId();//item

export._uerId;//undefined
export._typeId;//undefined
export.converter;//undefined

闭包陷阱

var tasks = [];

for (var i=0; i<3; i++) {
    tasks.push(function() {
        console.log('>>> ' + i);
    });
}

console.log('end for.');

for (var j=0; j<tasks.length; j++) {
    tasks[j]();
}

输出结果都为3。这个问题的原因在于,函数创建时并未执行,所以先打印end for.,然后才执行函数,由于函数引用了循环变量i,而i的作用域是整个函数,而不是循环,在函数执行时,i的值已经变成了3。

解决方法
再创建一个函数,将循环变量作为函数参数传入:

var tasks = [];

for (var i=0; i<3; i++) {
    var fn = function(n) {
        tasks.push(function() {
            console.log('>>> ' + n);
        });
    };
    fn(i);
}

//简化语法,直接用匿名函数的立即执行模式(function() { ... })()

var tasks = [];

for (var i=0; i<3; i++) {
    (function(n) {
       tasks.push(function() {
           console.log('>>> ' + n);
        });
    })(i);
}

总结

优点:灵活方便,封装
缺点:空间浪费,内存泄漏,性能消耗

猜你喜欢

转载自www.cnblogs.com/y-dt/p/9382782.html