关于使用实际封闭的怀疑

时间:2012-04-27 09:35:10

标签: javascript closures

我正在尝试在Javascript中找到有关闭包的更多信息,并且正在经历这个问题:https://developer.mozilla.org/en/JavaScript/Guide/Closures#Practical_closures

根据这篇文章,通过使用这样的功能:

function makeSizer(size) {  
    return function() {  
        document.body.style.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;

虽然我理解这里的概念 - 即size12,size14和size16成为允许访问内部函数的闭包,但我不禁觉得这是不必要的。是不是更容易:

function makeSizer(size) {  
    document.body.style.fontSize = size + 'px';  
}   

,然后用这些调用它?

document.getElementById('size-12').onclick = makeSizer(12);  
document.getElementById('size-14').onclick = makeSizer(14); 
document.getElementById('size-16').onclick = makeSizer(16);

任何人都可以告诉我,我的想法是否正确 - 或者我可能只是Javascript的新手并且不了解在这种情况下使用闭包的优势,在这种情况下,如果你能解释我会很高兴这样做的好处。

先谢谢你们。

3 个答案:

答案 0 :(得分:3)

不,你做不到。

就像你写的那样:

document.getElementById('size-12').onclick = (function(size) {  
    document.body.style.fontSize = size + 'px';  
})(12);

该函数立即调用 ,样式将立即应用,并且没有.onclick处理程序被注册,因为该函数的返回值为undefined

该示例的真实要点是显示您可以从另一个函数返回一个函数,然后您可以将该结果分配给事件处理程序。


如果您未对makeSizer()进行修改,则可以根据建议分配处理程序而不使用中间变量,即:

document.getElementById('size-12').onclick = makeSizer(12);

但如果您按照描述的方式更改makeSizer(),那么将不会

如果您多次使用相同的sizer,它也比将“sizer”存储在变量中效率低。

答案 1 :(得分:1)

是的,那些变量(sizeN)是不必要的。您可以直接将makeSizer()的结果指定为处理程序,这看起来要好得多。

但是,使用这些变量并不是闭包的概念。此示例中的闭包是函数makeSizer,它返回函数(即使没有参数),它仍然可以访问size变量。

但是,您需要看到

之间的区别
function makeSizer(size) {  
    return function resize() {  
        document.body.style.fontSize = size + 'px';  
    };  
}

function resize(size) {  
    document.body.style.fontSize = size + 'px';  
}

执行makeSizer(5)没有做任何事情,它返回一个函数,在调用时将大小设置为预定义的大小。而是执行resize(5)会直接设置大小。您不能将后一个函数的结果用作事件处理程序。

答案 2 :(得分:1)

对于您提供的示例,当然不需要关闭,但我想这只是为了简化呈现概念。有些情况虽然闭包是最好的解决方案:考虑如何在javascript中实现“私有”属性,或者当你需要curryng来封装参数时(例如,对于回调函数)。

我希望以下示例有所帮助:

var makeSequencer = function() {
    var _count = 0; // not accessible outside this function
    var sequencer = function () {
        return _count++;
    }
    return sequencer;
}

var fnext = makeSequencer();
var v0 = fnext();     // v0 = 0;
var v1 = fnext();     // v1 = 1;
var vz = fnext._count // vz = undefined