我正在尝试在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的新手并且不了解在这种情况下使用闭包的优势,在这种情况下,如果你能解释我会很高兴这样做的好处。
先谢谢你们。
答案 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