JS-闭包

63 阅读2分钟

引言

因为想把自己的想法实现光会后端还是不够的,所以开始学习JS.

闭包

闭包让开发者可以从内部函数访问外部函数的作用域.闭包会随着函数的创建而被同时创建. 允许将函数与其所操作的某些数据(环境)关联起来.

案例

实用的闭包

通常使用只有一个方法的对象的地方,都可以使用闭包.

function makeSizer(size) {
    return function () {
        document.body.size.fontSize = size + "px"; 
    }
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;

使用闭包模拟私有方法

js没有原生支持方法私有化(话说Class不是支持了私有方法嘛?)

var Counter = (
    function () {
        var privateCounter = 0;

        function changeBy(val) {
            privateCounter += val;
        }
        
        return {
            increment: function () {
                changeBy(1);
            },
            
            decrement: function () {
                changeBy(-1);
            },
            
            value: function() {
                return privateCounter;
            }
        }
    }
)();

创建了一个立即执行的匿名函数体,包含了两个私有变量和方法,同时创建多个实例,闭包之间互不影响.

让这些变量的值始终保持在内存中

function f1() {
    var n = 999;
    nAdd = function () {
        n += 1
    }

    function f2() {
        alert(n);
    }

    return f2;
}

var result = f1();
result(); // 999
nAdd();
result(); // 1000

由于f2被赋值给了result,导致f1和内容变量n一直存在于内存中. nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量.其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包, 所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作.

思考题

var name = "The Window";
var object = {
    name: "My Object", 
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    }
};
alert(object.getNameFunc()()); // The Window
var name = "The Window";
var object = {
    name: "My Object", 
    getNameFunc: function () {
        var that = this;
        return function () {
            return that.name;
        };
    }
};
alert(object.getNameFunc()()); // My Object

重点在于this指针的指向问题,return function()其实是一个匿名的全局函数,则this是指向Window对象.

性能考量

如果不是某些特定任务需要使用闭包,在其他函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响.

参考资料