jQuery中的匿名函数语法

5

我已经阅读了很多与jQuery及其语法相关的文章。然而,我并没有完全理解它的语法,我真的很想更好地深入了解它。

许多文章未能指出简单的语法规则(以及它们的必要性)。

就目前而言,我正在经历一种语法理解难题:

我的HTML:

<body>
    <a href="http://www.jquery.com" title="anchor1">jQuery.com</a>
    <a href="http://www.jquery.com" title="anchor2">jQuery.com</a>
    <a href="http://www.jquery.com" title="anchor3">jQuery.com</a>

    <!-- JQUERY -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

    <script>
        (function ($) {
            // EXAMPLE 1
            $("a").each(function () {
                console.log(this.title);
            });
        })(jQuery);                      // ... everything works fine.


        (function ($) {
            // EXAMPLE 2
            $("a").each(function () {
                console.log(this.title);
            });
        });           // ... missing (jQuery). Why isn't this working?


        $(function () {  // ... notice the $ at the beginning.
            // EXAMPLE 3
            $("a").each(function () {
                console.log(this.title);
            });
        });           // ... missing (jQuery). Why IS this working?


            // EXAMPLE 4
            $("a").each(function () {
              console.log(this.title);
            });                          // ... everything works fine.
    </script>
</body>  

我将阐述我对代码的理解,如果你能以非常基础的方式回答我的问题,我会非常感激。请指出我所有的误解! 我的理解和问题: 示例1: 我创建了一个匿名JavaScript函数。这个函数在浏览器读取它的那一刻就被执行了。我传递给它jQuery对象(使用$,但我不知道为什么这很重要)。从现在开始,我的函数“说”jQuery(我假设它理解其语法)。在我的JavaScript函数的最后,我再次传递了jQuery对象(但为什么需要这样做呢?)。请启发我。 示例2: 我尝试了没有(jQuery)的相同函数。现在它不起作用了。我知道缺少什么。但是为什么末尾的(jQuery)如此重要? 示例3: 现在我用$开始了我的Javascript函数,我认为从现在开始我的整个函数都被包裹在一个jQuery对象中。在这个jQuery对象内,我的函数理解jQuery语法。在末尾,不需要(jQuery)。 示例4: 在这里,我没有构建JavaScript函数。我只使用jQuery选择并返回("a")。这段代码在浏览器读取它的那一瞬间就被执行了,不需要等待文档准备好。 我的问题基本上是: 在示例1中,为什么开头的$和结尾的(jQuery)都是必需的?它们的目的是什么?
我真的希望有更长的答案,这样我就能更深入地理解“正确阅读jQuery语法”以及谈论jQuery语法及其要求。谢谢。

1
问问自己 - $ 是什么? - u_mulder
@u_mulder,$代表jQuery。据我所知。$( ) === jQuery( )。 - stylesenberg
4个回答

9
我创建了一个匿名的JavaScript函数。这个函数会在浏览器读取它的那一刻立即执行。
不完全正确。你创建了一个函数表达式。
function () { }

然后你接着使用 () 调用它,稍晚一点。

你也可以这样做:

var myfunction = function ($) { ... };
myfunction(jQuery);

我传递了jQuery对象(使用$),但我不知道为什么这一点很重要。你正在定义一个函数。它接受一个参数,该值被分配给名为$的本地变量。从现在开始,我的函数“说”jQuery(它理解其语法-我假设如此)。语法属于JavaScript,而不是jQuery。在我的JavaScript函数的最后,我再次传递了jQuery对象(但为什么需要呢?)。请启示我。你第一次传递jQuery对象。这是你调用函数时传递给函数的参数。jQuery的值(jQuery对象)赋给本地变量$。这用于两个目的:1.让您使用$变量,而不必担心它被Prototype JS,Mootools或任何其他库覆盖,这些库认为将$作为变量名称非常通用;2.它使您具有不会污染全局范围的局部变量。()很重要,因为没有它们,您无法调用函数。jQuery很重要,否则函数内的$将为未定义。在这里,您使用函数表达式作为参数调用函数$()。$是一个多功能的函数,根据您传递的参数类型,它会执行许多不同的操作。如果传递一个函数,则它将将该函数分配为文档就绪事件处理程序。当DOM加载完成时,事件将触发并调用函数。是的。

我知道这个问题很老了,但这是一个关于匿名函数的绝佳解释。谢谢。 - Difster

6
首先,"jQuery 语法"并不存在。 jQuery 是一个 JavaScript 库,因此其语法就是 JavaScript 语法。
举个例子:我创建了一个匿名的 JavaScript 函数。这个函数在浏览器读取它的那一刻就被执行了。我把 jQuery 对象作为参数传递给了它(用 $ 表示,但我不知道这一点为何如此重要)。从现在开始,我的函数就能够“说” jQuery(我猜它理解了 jQuery 的语法)。在我的 JavaScript 函数的最后,我再次将 jQuery 对象传递给它(但这是为什么呢?请给我解释一下)。
你似乎知道函数和参数的工作原理。所以看看你的代码吧。
(function ($) {
        // EXAMPLE 1
        $("a").each(function () {
            console.log(this.title);
        });
    })(jQuery);

您定义了一个匿名函数,该函数接受一个参数:一个名为$的变量,在语句$("a")中使用。然后您调用匿名函数并将其传递给jQuery对象,因此在函数内部,$ === jQuery

示例2:我尝试了相同的函数,但没有在末尾加上(jQuery),现在它不起作用了。我知道缺少什么。但是为什么在末尾加上(jQuery)这么重要呢?

  1. 如果没有末尾的(),则甚至不会调用您的函数。您只是定义它,然后失去了它,因为您没有将其分配给变量。
  2. 如果只写(),也不会起作用,因为函数参数$将是未定义的,并覆盖全局$window.$)。

但是,如果您仅声明函数为function(),我认为它会工作,因为$将指向window.$

示例3:现在我以$开头启动了我的JavaScript函数,并且我认为从现在开始,整个函数都包含在jQuery对象中。在这个jQuery对象内,我的函数理解jQuery语法。最后不需要(jQuery)。

现在您使用一个参数调用$作为函数:您的匿名函数。

示例4:这里我没有构建JavaScript函数。我只是使用jQuery选择并返回了("a")。此代码在浏览器读取它的那一刻立即执行。无需等待文档准备就绪。

是的,您确实构建了一个函数,并将其作为参数传递给$("a")返回的对象的each()函数。

我的问题基本上是:
在示例1中,为什么开头的($)和末尾的(jQuery)都是必要的?它们的目的是什么?

参数有何作用?

但是您似乎不理解的是:$只是一个变量(或者如果您愿意,可以是一个函数,但在JS中函数变量)。


5
你的问题的解决方案在于理解 JavaScript 中的闭包......而不是 jQuery,jQuery 只是使用闭包。
利用闭包,你可以对其内部内容进行限制,并将参数传递给该闭包以供使用。
对于你的第二个示例,如果将 jQuery 传递给闭包,它会正常工作。例如:
(function ($) 
{
  $("a").each(function () {
    console.log(this.title);
  });
})(jQuery); // arguments passed in here

因为你在结尾没有传入jQuery,所以参数$是未定义的,因此无法在$('a')中调用。按照我所更改的方式编写,jQuery被分配给$参数,这个$参数可用于闭包内的代码。
同样的,在你的第3个示例中,你也没有传入jQuery,而且在闭包中也没有变量$,因此它将不起作用。请注意,你可以将其更改为以下内容(仅供说明):
(function (thisIsJquery) 
{
  thisIsJquery("a").each(function () {
    console.log(this.title);
  });
})(jQuery);

现在jQuery被分配给参数thisIsJquery,并在闭包内可用。
至于你的第四个例子,$被用于它定义的闭包中(而不是另一个闭包内),因此可以随时使用。
闭包是在JavaScript中隐藏实现并提供一种使事物私有的良好方式。
进一步阅读: http://www.w3schools.com/js/js_function_closures.asp https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

3
我将只关注不起作用的部分。以下是代码片段:

(function ($) {               
   $("a").each(function () {
     console.log(this.title);
   });
}) // not calling function

首先,您没有调用函数。因此,它内部的任何内容都不会运行。因此,您可能认为在最后添加()可以解决它。
但这还不是全部!
因为$指的是外部的jQuery。但由于您将命名参数作为$并且没有向其传递任何内容,因此片段内部的$会遮盖外部的$。由于它没有被赋值,它是undefined。因此,您最终会得到:
undefined is not a function

为了证明这一点,添加 ($) 将起作用,因为现在,命名参数 $ 指的是指向 jQuery 的 $

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