JavaScript将代码包装在匿名函数中

33

我需要帮助理解jQuery插件编写的模式。有人能为我解释一下这段简单的代码吗?

(function($) { /* Code here */ })(jQuery);

我知道这是为了避免与使用相同$字符的不同插件发生冲突,但我无论如何都无法理解它的工作原理。参数$与被解析的jQuery对象有什么关系?

5个回答

67

让我们来分解一下:

(function($) { /* Code here */ })(jQuery);

首先,构造:

(function() {})();

创建一个立即执行函数表达式,通常称为IIFE。这是一个立即执行的函数而不是现在定义、稍后调用的函数。它本质上是一个匿名(未命名)函数,定义后立即执行。

然后,像这样将jQuery传递给它:

(function() {})(jQuery);

将jQuery作为第一个参数传递给立即执行的函数。然后,将第一个参数命名为$在函数内定义该符号,以对应于传递的第一个参数。

(function($) {})(jQuery);

展开后的形式如下:

(function($) {
    // you can use $ here to refer to jQuery
})(jQuery);

对于 jQuery 插件作者来说,这里有几个好处:

  1. IIFE 创建了一个本地的函数环境,因此您可以拥有变量作为您插件的“全局”变量,但实际上它们并不是全局变量,因此不会污染或与实际全局变量命名空间冲突。

  2. 您可以使用 $ 来编写 jQuery 代码,无论宿主程序是否已经为 jQuery 定义了该变量,因为您在函数内部局部定义了 $ 变量。



谢谢,伙计。太简单了。我卡住了,因为我纠缠在jquery会包装这个函数,并且在jQuery库中有一个预定义的jquery变量,这个包装函数使用它。 - Mintz
你解释得非常好! - Hasin Hayder

11
你那里的东西是这样的简写形式:
function anonymous_function($) {
    // Code here
};
anonymous_function(jQuery);

正如您所看到的,它允许在函数内使用$符号作为对jQuery对象的引用。


这更有意义。它帮助我澄清了jfriend00的答案。谢谢! - J May

2

+1对jfriend00的回答。

但在页面中包含jQuery会覆盖全局符号jQuery和$(请参见jQuery.js第9579行),可能会与定义全局$的其他库发生冲突。

因此,进一步采取措施以防止全局$冲突:

(function($) {
    // you can use $ here to refer to jQuery
})(jQuery.noConflict());

如下所示:

<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script>
(function($) {
   console.log('want $ to be jQuery here so want true: ' + ($ === jQuery));
})(jQuery.noConflict());
console.log('do not want $ to be jQuery here so want false: ' + ($ === jQuery));
</script>

2
JavaScript中的函数可以是语句或表达式。当您使用函数表达式时,可以像任何其他值一样传递它:
> console.log(function() { 1 + 1; });
> (function() {}) && doExpensiveWork();
// etc.

函数表达式可以立即调用,这种情况下该函数被称为立即调用函数表达式(或简称IIFE)
> (function() { console.log("IIFE running"); })();
IIFE running

这与创建函数并分两步调用它相同:
> var notAnIIFE = function() { console.log("running"); };
> notAnIIFE();
running

一段函数表达式当然可以带参数:
> var someFunction = function(x, y) { return x + y; };
> var seven = someFunction(3, 4);
> seven
7

因此,IIFE 也可以带参数调用:
> var seven = (function(x, y) { return x + y; })(3, 4);
> seven
7

在这种调用的情况下:
(function($) { /* do work with $ */ })(jQuery);

将绑定到名称jQuery的值作为参数$传递到函数表达式中。这类似于执行以下操作:
var initializePlugin = function($) {
    /* do work with $ */
};
initializePlugin(jQuery);

但它不会在父命名空间中留下任何痕迹(而在我们的第二个例子中,当我们完成设置插件后,initializePlugin名称仍然存在)。

2
在javascript中,函数会创建一个作用域,这不仅仅是关于$变量,还有局部于该函数的变量。而且,通过给$参数赋值,它成为了该函数内部的局部变量,可以安全地使用,指向jQuery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接