这是关闭的一个很好的例子吗?

时间:2012-06-26 05:27:16

标签: javascript function functional-programming closures

我认为这是一个example on MDN并且不明白为什么这是一件好事(TM)。

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

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

为什么以上优于以下?

function makeSizer(size) {  
        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;  

<a href="#" id="size-12">12</a>  
<a href="#" id="size-14">14</a>  
<a href="#" id="size-16">16</a>  

5 个答案:

答案 0 :(得分:2)

在这种情况下,size是附带的变量。调用makeSizer(12)将返回一个“记住”的函数引用.12。此函数引用被分配给元素上的单击处理程序(请参阅MDN示例中的其余代码)。它说:如果你点击我,请致电(执行)size12。点击这样,正文的字体大小变为'12px',因为从makeSizer(12)返回的函数引用被执行(附带的值为12)。

如果您已经使用过此功能,则可以立即调整字体大小。

function makeSizer(size) {  
        document.body.style.fontSize = size + 'px';  
}
var size12 = makeSizer(12);  
var size14 = makeSizer(14);  
var size16 = makeSizer(16); //=> now the font-size of the body is '16px'

想想你在这种情况下会发生什么:

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

点击#size-12后会发生什么?

您链接到jsfiddle example的链接的MDN页面。试试吧!

是我乐于留给社区中更加宗教的部分的事情。我想说这个闭包很有用,也许很方便。

答案 1 :(得分:1)

它们都不是更好,但它们的行为不同。

在您按如下方式调用返回的函数之前,第一个实际上不会调整大小:

size12();

你的第二个例子首先声明一个函数,然后调用它3次。您立即将大小设置为12px然后是14px,最后是16px。

答案 2 :(得分:0)

“好”的标准是什么?

在第一个示例中,您创建了一些必须调用才能完成工作的函数。尺寸保持在封闭状态,很难看到任何好处。您可能想要这样做:

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

var setSmall = makeSizer(8);
var setMedium = makeSizer(10);
var setLarge = makeSizer(14);

或类似,所以现在你打电话:

setSmall();

第二种情况下的函数应该被称为 setSize

封闭的另一个用途是:

var setSize = (function() {
  var sizes = {small: 8, medium: 10, large: 14};

  return function(size) {

    if (sizes.hasOwnProperty(size)) {
      document.body.style.fontSize = sizes[size] + 'px';
    }
  }
}());

setSize('small');

他们是“好”,“坏”还是其他什么取决于你对它们进行分类的标准。

答案 3 :(得分:0)

在第一个示例中,makeSizer返回一个函数。在第二个示例中,它不返回任何内容,并且具有误导性的名称。两者完全不同。

第一个例子中的推理是makeSizer是函数工厂;它使“sizer”功能。 size12size14size16是由makeSizer制作的特定“sizer”函数。如果稍后调用其中一个,它将设置字体大小。

在第二个示例中,首先将字体大小设置为12,然后设置为14,然后设置为16,并在每个阶段将不感兴趣的返回值保存到变量中。

答案 4 :(得分:0)

实际上,你所拥有的是而不是一个闭包的例子。

维基百科告诉我们,closure的定义是“函数以及该函数的非局部变量的引用环境。”

更简单地说,它是一个“包围”周围范围变量的函数。

一个很好的例子是这样的:

public Func<int> ClosureExample()
{
    int a = 1,
        b = 2;

    Func<int> closeIt = () => a + b;
    return closeIt;
}

让我们真正看看这是怎么回事。我们声明两个整数,然后使用lambda表达式/ closure / anonymous方法(所有都是分配给第一类函数generic的定义的有效名称)来返回将用于执行此计算的第一类函数,使用随附的变量,在其他地方。

你可以说closeIt包含整数a和b;这些变量不属于闭包,但它们正在被它使用。