这是什么 JavaScript 表示法?

16

我在这里找到了它

;(function ($, window, document, undefined) {
//code
}(jQuery, this, this.document));

这是我第一次看到这样的东西。它是什么,该如何解释呢?我不明白为什么要通过this和this.document,还有'undefined'是什么意思。

我问这个问题的原因是因为我把它包含在我的页面中。

  if($('ul.mtree').length)

尽管在控制台中输入时它返回true,但它返回了false。


1
@ZachLeighton,这个问题有点令人困惑,但我认为George在问关于jquery文档加载的问题。 - Nathan Koop
我不明白为什么必须传递this和this.document,还有'undefined'是什么意思。 - George Irimiciuc
@NathanKoop 很好的发现,我匆忙看到了分号,以为是那个问题。 - Zach Leighton
1
为什么我们需要将window和undefined传递到这个jQuery插件中? - Igor Milla
@GeorgeIrimiciuc请更新问题并添加此信息。 - Nathan Koop
只是为了明确,这不是特殊的符号。它只是一个函数调用。 - Felix Kling
5个回答

16

首个分号;将其后的代码与之前可能忘记添加分号的任何其他代码区分开来。这很重要,因为如果没有找到分号,括号会尝试将前面的语句作为函数运行。

对于其余的代码,我们只是声明了一个“内联”函数,该函数将立即执行,其中参数$、window、document从全局作用域实例化为jQuery、this、this.document(分别)。这主要是为了在新的 jQuery 插件中可以使用"$",而不必担心$已在其他地方被覆盖。您可以确定$jQuery相同。

阅读更多关于“保护$别名和添加范围”的信息,请在这里

更新自原帖作者:

对于返回假值的if语句,请确保在调用if语句时加载了您的HTML内容。一种快速的方法是将其包装在$(document).ready方法中,如下所示:

$(document).ready(function () {
    if($('ul.mtree').length) {
         alert("got 'em!");
    }
});

1
仅仅提一下:它对于JS代码的压缩有很大帮助。 - Royi Namir
是的!@RoyiNamir说得好。 - KJ Price
1
另外,你忘了提到未定义的值可能会被用户代码覆盖(我认为现在不是这种情况),但最安全的做法是不向变量发送任何内容,这样你就可以确定它具有“未定义”的值。 - Royi Namir
很好,关于“未定义”,我错过了那个。 - KJ Price
文档准备就绪并没有解决这个问题,因为该示例使用的是旧版本的velocity。而当前版本不包括该函数(对于可能想运行该示例的所有人都是如此)。 - George Irimiciuc

3
这是一个立即执行函数。在开头的 ; 号可以防止缩小后出现潜在的语法错误。
该函数本身提供了参数作用域而不是在全局范围引用它们。它还提供了定义在函数中的局部变量的隐私。最后传递的有点令人困惑的 undefined 参数,保护免受对全局范围下 undefined 表示所做的恶意更改。
如果您搜索 javascript 术语,如自执行函数、全局范围、闭包、模块模式,将会找到很多资源。

关于 undefined 的提醒很好。我没注意到。 - KJ Price

2

如果您的代码无法正常工作,包含一份副本可能会有所帮助。

但是回答关于为什么在控制台中if($('ul.mtree').length)可以返回true,但在页面中可能会返回false取决于时机(例如,在DOM加载之前执行函数)。当您加载控制台以检查值时,DOM已加载并返回true。

确保将JS放置在页面末尾,或者仅在文档加载后调用。


可能会有帮助,为 OP 包括“文档加载”语法。 - KJ Price
好的,我最初没有包含它,因为我不想对 OP 的代码做任何假设。我本来想编辑它,但看起来你已经编辑了你的答案并包含了一个示例,所以我会保持不变,以限制重复。 - MichaelM

1

也许,这段代码的作用是修复 $, window 或者 document 被其他值覆盖的情况:

(function() {
var window = 123,
    document = 'abc',
    $ = Function.prototype;
})();

然后,
  • $jQuery 和其他库使用的简写。该代码假设 jQuery 没有被其他东西遮盖,因此创建了一个名为 $ 的变量,其值为 jQuery
  • this 是一个关键字。在非严格模式下未显式设置时,它将成为全局对象。因此,您的代码使用该值创建了一个名为 window 的本地变量。请注意,这很危险,因为在严格模式下,this 可能已被设置为某个值或为 undefined
  • 假设 this 是全局对象,则 this.document 将是文档对象。
  • undefined 是全局对象的属性,在 ECMAScript 3 中没有 ReadOnly 属性,因此可以被覆盖。您的代码创建了一个本地变量而没有分配任何值,因此它变成了真正的 undefined。自 ECMAScript 5 以来,这不再需要,因为 window.undefined 具有 [[Configurable]] 和 [[Writable]] 属性,均设置为 false
然后,
(function() {
var window = 123,
    document = 'abc',
    $ = Function.prototype;
    (function($, window, document, undefined) {
        // `$`, `window`, `document` and `undefined` have been restored
    })(jQuery, this, this.document);
})();

1
如果我理解你的问题正确,分号 ; 在函数声明前的作用如下:
(function(){
    console.log('no name');
})();

(function(){
    console.log('no name')
}());

-function(){
    console.log('no name');
}();

+function(){
    console.log('no name');
}();

~function(){
    console.log('no name');
}();

!function(){
    console.log('no name');
}();

你会看到记号,例如“()”,“-”,“+”,“~”,“!”

记号的作用是将函数语句解析为表达式并立即执行函数!

但我建议您只使用“()”来执行函数语句,因为这是日常使用中正式和规范的方式。


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