【问题标题】:What purpose does generating a closure inside of the $(document).ready() function accomplish?在 $(document).ready() 函数内部生成闭包有什么目的?
【发布时间】:2011-08-08 22:43:25
【问题描述】:

调试我的一个项目时,我注意到另一位开发人员更改了 $(document).ready() 函数以在其自身内部生成一个闭包。例如。 $(document).ready(function($) { });我很好奇这样做的意义,以及它的用法。

注意:通过从函数中删除$,我的代码再次工作。 $(document).ready(function() { })

原始/固定代码

$(document).ready(function() {
    var id = //pull session variable from asp session (yuck)
    var img = $('.photoLink');

    $('.photoLink').click(function() {
        $(this).photoDialog({
            id: id,
            onClose: function() {
                img.attr('src', img.attr('src') + '&rand=' + (new Date()).getTime()); //prevent caching of image
            }
        });
    });
});

修改/损坏的代码

$(document).ready(function($) {
    var id = //pull session variable from asp session (yuck)
    var img = $('.photoLink');

    $('.photoLink').click(function() {
        $(this).photoDialog({
            id: id,
            onClose: function() {
                img.attr('src', img.attr('src') + '&rand=' + (new Date()).getTime()); //prevent caching of image
            }
        });
    });
});

修改后的代码会在 FireBug 中产生错误,指出我调用的自定义插件函数不存在。我假设这是因为 $ 参数覆盖或与尝试使用它的任何 jQuery 函数发生冲突。

我真的很困惑为什么有人会改变它,在当前的上下文中它没有任何意义,因为该插件调用是页面上唯一的 javascript。

有人可以向我解释一下您为什么要使用它,并可能举个例子来说明它的用法吗?

编辑

以下是我的自定义插件的代码,我还修改了上面的示例以显示我是如何调用它的:

(function($) {
    var link = $('<link>');
    link.attr({
        type: 'text/css',
        rel: 'stylesheet',
        href: 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/themes/black-tie/jquery-ui.css'
    }).appendTo('head');

    var script = $('<script>');
    script.attr({
        type: 'text/javascript',
        src: 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js'
    }).appendTo('head');

    $.fn.photoDialog = function(options) {

        var defaults = {
            autoOpen: false,
            title: 'Photo Tool',
            minHeight: 560,
            minWidth: 540,
            url: '/photo_form.aspx',
            onClose: function(){}
        };
        var opts = $.extend(defaults, options);

        return this.each(function() {
            $this = $(this);
            that =$(this);
            var $dialog = $('<div>')
                .html('<iframe src="' + opts.url + '?sn=' + opts.id + '" width="' + (opts.minWidth - 20) + '" height="' + (opts.minHeight - 20) + '" style="border: none;" scrolling="no"></iframe>')
                .dialog({
                    autoOpen: opts.autoOpen,
                    title: opts.title,
                    minHeight: opts.minHeight,
                    minWidth: opts.minWidth,
                    modal: true,
                    close: function() {
                        opts.onClose.call(that);
                    }
                });

            $this.click(function() {
                $dialog.dialog('open');
                return false;
            });
        });
    };
})(jQuery);

【问题讨论】:

  • 我刚刚在我的答案中添加了一个新理论...

标签: jquery closures document-ready


【解决方案1】:

当你编写一个 jQuery 插件时,为了支持 noConflict 特性,你通常会这样做:

(function($) {
    // Plugin code...
})(jQuery);

这允许您在插件代码中使用$ 作为jQuery 的别名,而不管noConflict 设置如何。

也许其他开发者通过反射添加了$ 参数。

三思而后行。其他开发人员可能正在尝试改善这种情况。

即使将$ 参数传递给ready 处理程序,您的代码也应该仍然有效。您说您调用的自定义插件功能不再存在。你能告诉我们更多关于那个自定义插件的信息吗?

我怀疑$ 正在对document.ready() 的调用和处理程序的实际执行之间发生变化,而您之前曾利用过这一点,但您不能再因为原来的$ 现在传递给处理程序。

【讨论】:

  • @jon3laze,好吧,显然插件不是这里的罪魁祸首。两个问题:jQuery(this).photoDialog() 有效吗?页面上是否还有其他脚本可以执行诸如将$ 设置为$.sub() 之类的操作?
  • 哦,您的插件代码在调用$(document).ready()之前被评估,对吧?
  • TG 用于 NP++,搜索 $ 并发现他在 asp 中复制了调用......对我来说绝对没有意义,但我已经删除了重复并且它有效。我只查看了 JS 而不是 asp :P
  • @jon3laze,这就是为什么我更喜欢我的脚本在他们自己的文件中,而不是在某个地方的其他代码中内联。很高兴你能解决你的问题:)
【解决方案2】:

$(document).ready(... 内部传递给函数的第一个参数是 jQuery 对象。您所看到的模式只有在您拥有时才真正有意义

// outside here, $ could be anything   

jQuery(document).ready(function($) {
    // $ inside here refers to jQuery
    $('.element').click(function() {
        //call custom plugin here
    });
});

这将允许 $ 别名引用函数内部的 jQuery 以在 DOM 加载时执行,即使 window.$ 不引用 jQuery 而是其他东西,例如另一个 JavaScript 库函数.但是你的问题是什么,只要window.$ 引用jQuery,那么我希望代码可以正常工作。

【讨论】:

  • 这不是问题所在,但就使用 $ 而言最有意义。 +1
【解决方案3】:

jQuery 将对全局“jQuery”的引用传递给“就绪”处理程序。这就是代码会以这种方式编写的原因,实际上 应该 没有问题。我怀疑这个故事比你的问题所揭示的更多。

edit — 有一种可能: 可能是您的插件正在导入一个 单独的 jQuery 副本,并且它自己安装在那个,而不是你的?您可以尝试使用 TamperData 之类的工具或 Chrome“网络”开发人员工具来查看所有 HTTP 请求并查看 jQuery 是否被加载了两次。或者,将此行放在“Broken”代码之前:

$.banana = "yellow";

然后检查处理程序代码中的“$”是否具有“香蕉”属性。

如果是这种情况,那么不同之处在于“Broken”代码中对“$”的引用将是对未安装插件的 jQuery 副本的引用。当您取出“$”参数时,代码可以引用正确的、更新的库副本。

【讨论】:

  • 我在插件中导入 jquery ui,但不是基础框架的附加部分。我发布了我的插件的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多