2

我试图在 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 的新手并且不了解在这种情况下使用闭包的优势,在这种情况下,如果你能解释一下我会很高兴这样做。

提前谢谢各位。

4

3 回答 3

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”存储在变量中效率低。

于 2012-04-27T09:41:41.773 回答
1

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

但是,这些变量的使用并不是闭包的概念。这个例子中的闭包是 function 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)会直接设置大小。您不能将后一个函数的结果用作事件处理程序。

于 2012-04-27T09:45:06.907 回答
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
于 2012-04-27T09:59:04.760 回答