0

这可能有点抽象,但我正在尝试了解 JavaScript 闭包等。请使用以下代码:

function MyObj() {
    var me = this;

    this.foo = function(bar) {
        // Do something with 'bar'
    }

    // Set up lots of local variables etc.
    // ....

    $(window).load(function() {
        // Add a delegated click handler to specific <input> elements
        $(document).on('click.myobj', 'input.special', function() {
            // Do something with the <input> that triggered the click event
            me.foo(this);
        });
    });
}

var myObj = new MyObj();

传递给它的匿名函数绑定到 click 事件创建一个引用的闭包me。我想知道的是做这样的事情是否更好(以避免关闭):

$(window).load(function() {
    // Add a delegated click handler to specific <input> elements
    (function(localMe) {
        $(document).on('click.myobj', 'input.special', function() {
            // Do something with the <input> that triggered the click event
            localMe.foo(this);
        });
    })(me);
});

这是更好的方法,还是我对创建闭包过于偏执?或者,是否有“第三种方式”?


编辑

此外,做这样的事情会更好吗:

$(window).load(function() {
    // Add a delegated click handler to specific <input> elements
    $(document).on('click.myobj', 'input.special', {localMe : me}, function(event) {
        // Do something with the <input> that triggered the click event
        event.data.localMe.foo(this);
    });
});
4

4 回答 4

1

如果您从构造函数绑定事件,您将始终创建一个闭包。事实上,您甚至需要闭包来保留对您的实例的引用。但是,您可能会执行以下操作:

function MyObj() {
    this.foo = function(bar) {
        // Do something with 'bar'
    }

    // Set up lots of local variables etc.
    // ....
}

var myObj = new MyObj();
$(function() {
    $(document).on('click.myobj', 'input.special', function() {
        myObj.foo(this);
    });
});

如果您只创建构造函数的单例实例,那么无论如何都没关系。

于 2012-12-05T14:49:15.710 回答
1

匿名函数现在在 javascript 中大量使用(作为参数和作用域/闭包的直接函数)。没有性能问题。

但是您可能会遇到代码阅读问题。因为当你看到一个变量时,你必须检查变量来自哪里。但这里没什么大不了的。

在您的第二个示例中,您仍然有一个闭包“中断”。因为在你的匿名函数中click,你使用了localMe变量。并且localMe是您的功能之外的功能的参数。

// Here, 'me' is a direct local variable.
$(window).load(function() {
    // Here, we are in an anonymous fonction, so 'me' is not a direct variable anymore. But you still can access it.

    // Add a delegated click handler to specific <input> elements
    (function(localMe) {
        // Here, 'localMe' is a direct local variable.
        $(document).on('click.myobj', 'input.special', function() {
            // We are in an anonymous function, so 'localMe' is not a direct variable anymore.

            // Do something with the <input> that triggered the click event
            localMe.foo(this);
        });
    })(me);
});

如果你真的想避免闭包“中断”,你应该将你的函数绑定到你的对象。但请注意,并非每个浏览器都支持bind函数上的方法。

于 2012-12-05T11:58:21.663 回答
1

后者(AFAIK)效率更高,但除非在紧密循环中使用,否则可能无法测量。

原因是所有变量解引用都必须遵循作用域链。在后一种情况下,localMe可以在匿名函数的参数列表中找到该变量。

在前一种情况下,变量不是在那里找到的,而是在外部范围内。这种向上遍历作用域链需要额外的时间。

于 2012-12-05T12:04:25.630 回答
0

我可能会这样做:

var bind = function( fn, me ) { return function() { return fn.apply(me, arguments); }; },
    Object = (function() {
        function Object() {
            this.handler = bind(this.handler, this);
            // Add a delegated click handler to specific <input> elements.
            $(document).on("click.myobj", "input.special", this.handler);
        }

        Object.prototype.foo = function( bar ) {
            // Do something with "bar".
        };

        Object.prototype.handler = function( event ) {
            // Do something with the <input> that triggered the click even.
            return this.foo(event.currentTarget);
        };

        return Object;
    })();

var obj = new Object();

这跳过了闭包和 iifes 的使用,而是使用.apply。不确定它是否更有效,但这是另一种选择。

于 2012-12-05T12:16:24.737 回答