对象中的闭包或处理程序?

时间:2011-12-04 20:11:21

标签: javascript

我点击一个按钮,然后有一个处理程序。我从来没有理解我是否应该使用闭包,或让处理程序在一个对象中。例如,在HTML中我有,

<button id="b">Go</button>
<button id="c">Go</button>

和JavaScript(带有一些jQuery),

var hdl=function(){
    var hdl=function(){
        foo+="foo"
        console.log(foo)
    }, 
    foo="" 
    return hdl
}()
$("#b").click(hdl)

var obj={
    bar:"",
    hdl:function(){
        this.bar+="bar"
        console.log(this.bar)
    }
}
var baz=function(){
    obj.hdl()
}
$("#c").click(baz)

两者都有效。或者您是否只能使用其中一种?

3 个答案:

答案 0 :(得分:3)

事件处理程序始终是实现EventListener接口的函数或对象。我从来没有理解使用EventListener对象而不是函数的任何理由,所以我只看到使用过的函数,但是你可以使用它们。

如果选择一个函数,则由您决定是将函数作为全局函数,匿名声明的函数还是作为对象属性的函数。没有“正确”的答案,因为它取决于您希望如何构建代码。

我的事件处理程序通常是匿名声明的函数,因为这通常是我构建事物的方式,通常不再需要它。 简单是最好的,所以你应该让它变得不再复杂。

闭包只是一个函数体,它比函数的简单执行存活的时间更长,因为其中一些其他函数引用仍处于活动状态。是否使用闭包取决于您的需求以及代码的结构。闭包可以非常方便地保留一些状态而不使用全局变量,但有时候根本不需要它们。

答案 1 :(得分:1)

我认为你在混淆条款。

闭包是JavaScript的范围规则的自然结果,而不是您选择创建的

jQuery click事件始终需要一个函数。该函数是否附加到对象 - 从而使其成为一种方法 - 并不重要。根据函数的编写方式,它可能形成一个影响你的闭包。

闭包是指函数“记住”定义它的上下文中的变量。

经典的闭包示例是这样的:

for(var i = 0; i < 10; i++)
    $("#button" + i).click(function() { alert("you clicked button " + i); });

大多数开发人员都惊讶地发现每个按钮显示10,当外部范围结束时,这是i的值。发生这种情况是因为循环中声明的每个函数都在i上形成了一个闭包。这些函数不仅在声明它们时获得i的值,它们获得实际的i,尽其所能。这就是为什么在创建函数后更改i会导致创建的函数反映i的更新值

通过将i传递给函数,打破闭包来修复这样的情况,因为函数参数是按值传递的。

for(var i = 0; i < 10; i++)
     (function(localI) {
         $("#button" + i).click(function() { alert("you clicked button " + localI); });
     )(i);

答案 2 :(得分:1)

您的案例之间的唯一区别是,在其中一个案例中,您将变量(foo)捆绑在一个对象中。以下第三个例子应该明确这一点:

function hdl(variables){
   variables.foo += variables.foo;
}

var obj = {foo: ""};
var baz = function(){
    hdl(obj);
}

我认为这些替代品中的任何一种都无论如何都优于其他替代品。您应该决定使用哪种解决方案更简单,更容易理解和维护,具体取决于您的特定问题。

例如,在使用对象的版本中,变量是dinamically绑定的,而在带有闭包的版本中,它们是静态绑定的。这意味着对象版本更具可扩展性(使用继承,mixins等),而闭包版本更加严格(但在编译时更容易理解)