0

我在 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>  
4

5 回答 5

2

在这种情况下size,是封闭的变量。调用makeSizer(12)返回一个“记住”的函数引用 12。这个函数引用被分配给一个元素上的点击处理程序(参见 MDN 示例中的其余代码)。它说:如果您点击我,请致电 (execute) 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吗?

您链接到的 MDN 页面链接到jsfiddle 示例。试试看!

好的的事情我很乐意留给社区中更宗教的部分。我会说这个闭包很有用,甚至可能很方便。

于 2012-06-26T05:38:13.550 回答
1

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

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

size12();

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

于 2012-06-26T05:39:47.670 回答
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');

它们是“好”、“坏”还是其他取决于您对它们进行分类的标准。

于 2012-06-26T05:49:20.963 回答
0

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

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

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

于 2012-06-26T08:49:11.287 回答
0

实际上,您所拥有的并不是闭包的示例。

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

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

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

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

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

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

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

于 2012-06-27T14:47:54.887 回答