什么!function($){$(function(){})}(window.jQuery)呢?

Gri*_*a U 61 jquery jquery-tooltip

我正在使用twitter bootstrap创建一个站点,并试图初始化工具提示.除了添加如下内容:

 $("[rel=tooltip]").tooltip()  
在application.js中,除非我保留,在bootstrap文档中使用以下代码,我的工具提示不会初始化.

!function ($) {

  $(function(){  

  })

}(window.jQuery)

上面的代码是做什么的?

Pra*_*Nag 162

让我们解释一下破解代码

function () {
}()
Run Code Online (Sandbox Code Playgroud)

或者经常写成

(function () {
})()
Run Code Online (Sandbox Code Playgroud)

是一个self-invoking anonymous函数,也称为立即调用函数表达式(IIFE).其中立即执行内联匿名函数.

解释封装的匿名函数语法中阅读更多相关内容.

匿名函数是一个强大的功能,并具有类似作用域("变量名称间距")的好处,请参阅javascript中自执行函数的用途是什么?.


现在他们正在使用

function ($) {

}(window.jQuery)
Run Code Online (Sandbox Code Playgroud)

我们暂时跳过它!.

所以他们正在传递window.jQuery这个函数作为参数并接受为$.

它的作用是$window.jQuery(原始jQuery对象)创建一个别名,从而确保$将始终引用jQuery object内部closure,无论其他库是否已将该($)放在外部.

因此,您在封闭使用中编写的代码$将始终有效.

另一个好处是$作为匿名函数中的一个参数,它使它更接近scope chain,因此JS解释器$在闭包内找到对象所花费的时间比使用全局时所花费的时间要少$.


$(function(){  

})
Run Code Online (Sandbox Code Playgroud)

它是你可能已经知道的jQuery文档就绪块,它确保了这个函数内部的代码将在何时运行dom is ready,因此所有代码event binding's都能正常运行.

更多信息,请访问http://api.jquery.com/ready/

这里做了什么!已经很好地解释或者在感觉标记之前做了什么?

简而言之:

为了证明这些好处!,让我们考虑一个案例,

(function() {
    alert('first');
}())


(function() {
    alert('second');
}())
Run Code Online (Sandbox Code Playgroud)

如果您粘贴上面的代码console,您将收到两个警报,但随后您将收到此错误

TypeError: undefined is not a function
Run Code Online (Sandbox Code Playgroud)

为什么会这样?让我们模拟JS引擎如何执行上面的代码块.它执行这个匿名函数function() {alert('first');}()显示警报,因为它返回undefined内部没有返回任何内容().第二个功能也是如此.所以在执行这个块后,它最终会有类似的东西

(undefined)(undefined)
Run Code Online (Sandbox Code Playgroud)

因为它的语法就像一个self-invoking anonymous函数,它试图调用该函数,但第(undefined)一个函数不是函数.所以你得到undefined is not a function错误.!修复了这种或错误.会发生什么!.我引用了上面回答链接中的行.

使用!时,该函数将成为一元(逻辑)NOT运算符的单个操作数.

这会强制将函数作为表达式进行求值,从而允许立即内联调用它.

这解决了上面的问题,我们可以用!like 重写上面的块

!(function() {
    alert('first');
}())


!(function() {
    alert('second');
}())
Run Code Online (Sandbox Code Playgroud)

对于您的情况,您可以简单地将工具提示代码放在文档就绪块中

$(function(){  
    $("[rel=tooltip]").tooltip();  
});
Run Code Online (Sandbox Code Playgroud)

它会工作正常.

如果你只是在$("[rel=tooltip]").tooltip()没有任何东西的情况下使用doc ready block,那么这个代码就有可能运行,rel=tooltip而DOM中还没有任何元素.所以$("[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>
Run Code Online (Sandbox Code Playgroud)

作为浏览器,按顺序解释标记,它将在面对它时立即执行js代码.当它在这里执行JS块时,它尚未解析a rel="tooltip"标签,因为它出现在JS块之后,所以它们当时不在DOM中.

所以对于上面的情况$("[rel=tooltip]")是空的,因此工具提示将不起作用.因此,将所有JS代码放在document ready块中就可以了

$(function){
    // put all your JS code here
});
Run Code Online (Sandbox Code Playgroud)

希望这一切现在对你有意义.

  • 非常好,但是我认为对于使用`!`进行证明并不是很好.例如,当问题中没有外部问题时,答案使用`!(function(){}())`.更不用说你几乎从不在一个脚本中使用2个不同的`(function(){}())`作为"包装器".还可以补充一点,它可以通过在IIFE`(function(){}())之后放置一个分号来轻松修复;`我认为它比将返回值强制转换为布尔值更合理**. (7认同)
  • 谢谢你的回答! (6认同)
  • +1很棒的写作,在这里学到了很多.我认为这被称为*Canonical Answer*:) (5认同)