让我们通过拆分代码来解释
function () {
}()
通常写作
(function () {
})()
这是一个“自执行匿名”函数,也称为“立即调用函数表达式(IIFEs)”,它会立即内联执行匿名函数。
请在
Explain the encapsulated anonymous function syntax中了解更多相关信息。
匿名函数是一项强大的功能,具有诸如作用域(“变量名称空间”)等优点,请参见
What is the purpose of a self executing function in javascript?。
现在他们正在使用。
function ($) {
}(window.jQuery)
现在先忽略 !
。
他们将 window.jQuery
作为参数传递给函数,并接受为 $
。
这样做的作用是将 $
别名设置为 window.jQuery
(原始 jQuery 对象),因此确保在该闭包内,$
总是指向 jQuery 对象
,无论其他库是否将其 ($
) 取出。
因此,在使用 $
编写的闭包内的代码始终有效。
另一个好处是,$
作为匿名函数的参数出现,它在 作用域链
中更加接近,因此 JS 解释器查找闭包内的 $
对象所需的时间较少,而不是使用全局 $
所需的时间。
$(function(){
})
这是jQuery的文档就绪块,你可能已经知道了,它确保此函数内的代码将在dom准备好后运行,因此所有事件绑定将正常工作。
更多信息请参见http://api.jquery.com/ready/
而那个!
的作用已经在这里或在函数前面加感叹号有什么作用?中得到了很好的解释。
简而言之:
为了演示!
的好处,让我们考虑一个情况,
(function() {
alert('first');
}())
(function() {
alert('second');
}())
如果您将上述代码粘贴到
控制台
中,您将收到两个警报,但随后会出现此错误。
TypeError: undefined is not a function
为什么会发生这种情况?让我们模拟一下JS引擎执行上述代码块的过程。它执行这个匿名函数
function() {alert('first');}()
,显示警报,由于它没有返回任何内容,所以在
()
内返回
undefined
。第二个函数也是同样的情况。因此,在执行完这个块之后,它最终会变成类似这样的东西。
(undefined)(undefined)
由于它的语法类似于“自调用匿名”函数,因此它试图调用该函数,但第一个“(undefined)”不是函数。因此,您会得到“undefined is not a function”错误。 “!”可以解决这种类型的错误。使用“!”会发生什么。我引用了上面答案链接中的行。
当您使用!时,函数成为一元(逻辑)NOT运算符的单个操作数。这迫使函数作为表达式进行评估,从而允许它立即内联调用。
这解决了上述问题,我们可以使用“!”重写上面的块。
!(function() {
alert('first');
}())
!(function() {
alert('second');
}())
对于您的情况,您可以将您的工具提示代码放在文档准备块内,像这样:
$(function(){
$("[rel=tooltip]").tooltip();
});
它将能够正常工作。
如果您只是使用 $("[rel=tooltip]").tooltip()
而没有任何 doc ready block
,那么当这段代码运行时,DOM 中可能还不存在任何具有 rel=tooltip
的元素。因此,$("[rel=tooltip]")
将返回一个空集合,tooltip
将无法工作。
以下是一个示例标记,如果没有 doc ready block
,则它将无法正常工作:
.
.
.
<script type="text/javascript">
$("[rel=tooltip]").tooltip();
</script>
.
.
.
.
<a href="#" rel="tooltip">Something</a>
<a href="#" rel="tooltip">Something</a>
<a href="#" rel="tooltip">Something</a>
作为浏览器,它会按顺序解释标记,并在遇到JS代码时立即执行。当它执行此处的JS块时,它尚未解析
a rel="tooltip"
标记,因为它出现在JS块之后,所以它们在那时不在DOM中。
因此,在上述情况下,
$("[rel=tooltip]")
为空,因此工具提示将无法正常工作。因此,将所有JS代码放在
document ready
块中始终是安全的。
$(function){
});
希望现在对您来说所有这些都是有意义的。
!
的理由而且表述不够好。例如,在问题中没有外部括号时,答案使用了!(function(){}())
。更不用说你几乎永远不会在单个脚本中使用两个不同的(function(){}())
作为“包装器”。还可以补充一点,通过在 IIFE 后添加分号来轻松解决这个问题,即(function(){}());
,我认为这比将返回值强制转换为布尔值要合理得多。 - Fabrício Matté$
将始终在IIFE内引用jQuery
对象。 - Prasenjit Kumar Nagfunction(...){...}()
这样的写法是不合法的,应该使用(function(...){...})()
。 - matpop