【问题标题】:What does !function ($) { $(function(){ }) }(window.jQuery) do?!function ($) { $(function(){ }) }(window.jQuery) 做什么?
【发布时间】:2012-06-09 10:30:28
【问题描述】:

我正在使用 twitter bootstrap 创建网站并尝试初始化工具提示。除了添加类似:

 $("[rel=tooltip]").tooltip() 
在 application.js 中,除非我保留,引导文档中使用的以下代码,我的工具提示不会初始化。 !函数 ($) { $(函数(){ }) }(窗口.jQuery)

上面的代码是做什么的?

【问题讨论】:

    标签: jquery jquery-tooltip


    【解决方案1】:

    让我们通过分解代码来解释

    function () {
    }()
    

    或常写成

    (function () {
    })()
    

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

    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 对象)的别名,从而确保$ 始终引用closure 中的jQuery object,无论其他库是否有把那个($)带到外面。

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

    另一个好处是$ 是匿名函数中的一个参数,这使得它在scope chain 中更接近,因此 JS 解释器在闭包内找到 $ 对象的时间比它要少如果我们使用全局$,否则会采用。


    $(function(){  
    
    })
    

    您可能已经知道,它是 jQuery 的文档就绪块,它确保该函数内的代码在 dom is ready 时运行,因此所有 event binding's 都将正常工作。

    阅读更多http://api.jquery.com/ready/

    ! 所做的事情已经在hereWhat does the exclamation mark do before the function? 得到了很好的解释

    简而言之:

    为了演示! 的好处,让我们考虑一个案例,

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

    如果你把上面的代码粘贴到console,你会得到两个警报,然后你会得到这个错误

    TypeError: undefined is not a function
    

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

    (undefined)(undefined)
    

    由于它的语法类似于self-invoking anonymous 函数,它会尝试调用该函数,但首先,(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){
        // put all your JS code here
    });
    

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

    【讨论】:

    • 感谢您的精彩回答!
    • @powtac,谢谢,我也是个新手,每天从 SO 那里学习 JS 的新东西。
    • +1 写得很好,在这里学到了很多东西。我认为这被称为 Canonical Answer :)
    • 非常好,但我认为证明使用! 的合理性太过分了,但不是很好。例如。当问题中没有外部括号时,答案使用!(function(){}())。更不用说您几乎不会在单个脚本中使用 2 个不同的 (function(){}()) 作为“包装器”。还可以补充说,通过在 IIFE (function(){}()); 之后放置一个分号很容易解决这个问题,我发现这比将返回值转换为布尔值更合理。
    • 所以我理解对了吗,如果我使用这个我就不需要 jQuery noConflict 模式?
    猜你喜欢
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 2012-11-15
    • 2011-11-27
    相关资源
    最近更新 更多