在 $(document).ready() 函数内部生成闭包的目的是什么?
调试我的一个项目时,我注意到另一位开发人员更改了 $(document).ready() 函数以在其内部生成一个闭包。 EG $(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);
Debugging one of my projects I noticed another developer had changed the $(document).ready()
function to generate a closure inside of itself. E.G. $(document).ready(function($) { });
I am curious as to the point of doing this, as well as it's usage.
Note: By removing the $
from the function my code works again. $(document).ready(function() { })
Original/Fixed Code
$(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
}
});
});
});
Modified/Broken Code
$(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
}
});
});
});
The modified code would produce errors in FireBug stating that the custom plugin function that I was calling did not exist. I am assuming this is because the $
argument is overriding or conflicting with any of the jQuery functions trying to use it.
I'm really confused as to why someone would have changed this, in the current context it makes no sense as that plugin call is the only javascript on the page.
Can someone explain to me why you would use this and possibly an example of it's usage?
Edit
Below is the code for my custom plugin, I also modified the examples above to display how I am calling it:
(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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您编写 jQuery 插件时,为了支持 noConflict 功能,您通常会这样做
:在插件代码中使用
$
作为jQuery
的别名,无论noConflict
设置如何。也许其他开发人员通过反射添加了$
参数。再想一想,删除它。另一位开发商可能正在努力改善这种情况。
即使将
$
参数传递给ready
处理程序,您的代码也应该仍然有效。您说您调用的自定义插件函数不再存在。您能告诉我们更多有关该自定义插件的信息吗?我怀疑
$
在调用document.ready()
和处理程序的实际执行之间发生变化,并且您之前已经利用了这一点,但您不能因为原始的$
现在已传递给处理程序。When you write a jQuery plugin, to support the noConflict feature, you usually do:
That allows you to use
$
as an alias forjQuery
within the plugin code, regardless of thenoConflict
settings.Maybe the other developer added the$
argument by reflex.On second thought, strike that. The other developer was probably trying to improve the situation.
Your code should still work, even with a
$
argument passed to theready
handler. You say the custom plugin function that you were calling does not exist anymore. Can you tell us more about that custom plugin?I suspect
$
is changing between the call todocument.ready()
and the actual execution of the handler, and you were taking advantage of that before, but you can't anymore since the original$
is now passed to the handler.传递给
$(document).ready(...
内部函数的第一个参数是 jQuery 对象。只有当您拥有此模式时,您所看到的模式才真正有意义。这将允许
$
别名,用于在 DOM 加载时在函数内部引用jQuery
,即使window.$
不引用jQuery 但还有其他东西,例如另一个 JavaScript 库函数,但是只要
window.$
引用jQuery
,那么我会期望代码可以毫无问题地工作。the first argument passed to the function inside of
$(document).ready(...
is the jQuery object. The pattern that you have seen only really makes sense if you hadThis would allow the
$
alias to referencejQuery
inside of the function to execute when the DOM has loaded, even ifwindow.$
does not referencejQuery
but something else, like another JavaScript library function for example. But what you have in your question, so long aswindow.$
referencesjQuery
, then I would expect the code to be working without problems.jQuery 将全局“jQuery”的引用传递到“就绪”处理程序中。这就是为什么代码会这样写,事实上应该没有问题。我怀疑这个故事比你的问题所揭示的更多。
编辑 - 这里有一种可能性:您的插件是否正在导入 jQuery 的单独副本,并且它会自行安装在该副本上你的?您可以尝试使用 TamperData 或 Chrome“网络”开发人员工具等工具来监视所有 HTTP 请求,并查看 jQuery 是否被加载两次。或者,将此行放在“Broken”代码之前:
然后检查处理程序代码以查看“$”是否具有“banana”属性。
如果是这种情况,那么区别在于“损坏”代码中对“$”的引用将是对未安装插件的 jQuery 副本的引用。当您取出“$”参数时,代码可以引用库的正确的、更新的副本。
jQuery passes a reference to the global "jQuery" into "ready" handlers. That's why the code would be written that way, and in fact there should be no problem with it. I suspect there's more to this story than your question reveals.
edit — here's a possibility: could it be that your plugin is importing a separate copy of jQuery, and that it installs itself on that one instead of yours? You might try using a tool like TamperData or the Chrome "Network" developer tool to watch all the HTTP requests and see if jQuery is being loaded twice. Alternatively, put this line before the "Broken" code:
and then check inside your handler code to see whether "$" has a "banana" property or not.
If that's the case, then the difference would be that references in your "Broken" code to "$" would be references to the copy of jQuery that did not have the plugin installed. When you take the "$" parameter out, then the code can refer to the correct, updated copy of the library.