在$(document).ready()函数内部生成闭包的目的是什么?

时间:2011-04-19 19:07:35

标签: jquery closures document-ready

调试我的一个项目我注意到另一个开发人员更改了$(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);

3 个答案:

答案 0 :(得分:3)

当您编写jQuery插件时,为了支持noConflict功能,您通常会这样做:

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

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

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

第二个想法,罢工。另一位开发商可能正试图改善这种情况。

即使将$参数传递给ready处理程序,您的代码仍然可以正常工作。你说你正在调用的自定义插件函数不再存在。你能告诉我们关于那个自定义插件的更多信息吗?

我怀疑$正在调用document.ready()和处理程序的实际执行之间发生变化,之前你正在利用它,但是你原来的{{1现在传递给处理程序。

答案 1 :(得分: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,那么我希望代码可以毫无问题地工作。

答案 2 :(得分:2)

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

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

$.banana = "yellow";

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

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