JavaScript函数中名为"undefined"的参数的目的是什么?

19

查看 jQuery 未压缩的源代码时,我遇到了一些不太理解的东西。当他们创建匿名函数时,他们将 undefined 作为第二个参数放置在函数参数列表中。这是做什么的?为什么要使用 undefined?在匿名函数中加上 undefined 参数是否是必需的?以下是一个示例,说明了我的问题。

(function( window, undefined)  {
  ...code here
})( window );

1
相关链接:https://dev59.com/cm445IYBdhLWcg3wIG19/ - Christian C. Salvadó
3个回答

20

这段代码的作用是在闭包内将undefined重新赋值给undefined。 这是一种安全措施,因为其他代码可能会意外执行类似以下的操作:

undefined = something;
console.log(undefined); // will output 'something'

在JavaScript中是有效的(如果使用的JS引擎未实现ECMAScript 5规范,在ECMAScript 5规范中,undefined是非non-writable的,参见MDN DOC )。

引用自MDNJavaScript 1.8.5新特性(ECMA 5)页面

全局对象变更

全局对象只读

根据ECMAScript 5规范,NaNInfinityundefined 全局对象已经被设置为只读

并且来自GitHub的ES5 Annotated Spec

ES5规范第x15.1.1.3

15.1.1.3 undefined

undefined的值是未定义的(请参阅8.1)。

该属性具有以下特征:{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

即使全局undefined不可写,您仍然可以拥有名为undefined的本地变量,并可能搞乱您的代码(主要是与undefined进行比较)。但这是您的责任。您可以编写如下代码:

(function(){
    console.log('Second Case: ');
    var undefined = 'Something';
    console.log(undefined); // Will log `something`
    var a ; // a is undefined
    console.log(a  ===  undefined); // false, as undefined is changed
    // you might expect a === undefined will return true, but as 
    // `undefined` is changed it will return false.
    console.log(a); // undefined
})();

演示: http://jsfiddle.net/joycse06/V4DKN/

然而,如果undefined是可写的,则上述赋值可能会干扰在该代码行之后进行的许多与undefined比较的操作,因为undefined不再是undefined。它现在具有某个值。

因此,他们正在像这样调用匿名函数:

( window ) // one argument only
我理解您需要的翻译是:

接收到

( window, undefined)  // only window is passed when calling the function
          // Second argument is not passed means it's undefined
          // so undefined is restored to undefined inside that function
          // and no global accidental assignments can hamper jQuery's 
          // code using 'undefined' now
那意味着在该闭包内部,undefined被恢复为undefined,因为它没有被传递任何值,从而保证在该匿名函数内部使用undefined
关于这个问题的一篇非常详细的文章,请参考http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/
我摘录了上述文章中的一些内容,以便说明清楚问题。 什么是undefined? 在JavaScript中有未定义(类型)未定义(值)未定义(变量)未定义(类型)是JavaScript内置的类型。 未定义(值)是原始值,也是Undefined类型的唯一值。
任何未被赋值的属性都会假定为未定义的值。(ECMA 4.3.9 and 4.3.10).
没有返回语句的函数或带有空返回语句的函数将返回未定义值。未提供函数参数的值为未定义。
var a;
typeof a; //"undefined"

window.b;

typeof window.b; //"undefined"



var c = (function() {})();

typeof c; //"undefined"



var d = (function(e) {return e})();

typeof d; //"undefined"

undefined (变量) 是一个全局属性,其初始值为 undefined (值)。由于它是一个全局属性,我们也可以将其视为变量进行访问。出于一致性考虑,在本文中我始终将其称为变量。

typeof undefined; //"undefined"
var f = 2;
f = undefined; //re-assigning to undefined (variable)
typeof f; //"undefined"

从ECMA 3版本开始,它的值可以被重新赋值:

undefined = "washing machine"; //assign a string to undefined (variable)
typeof undefined //"string"
f = undefined;
typeof f; //"string"
f; //"washing machine"

不用说,重新分配未定义变量的值是非常糟糕的做法,事实上它在ECMA 5中是不允许的。


1
console.log(undefined) .. 还是不打印? 没错,就是这样 :) - Luceos
所以,举个例子,如果我在匿名函数外部有一个“var undefined = 1”,并且我有一个匿名函数看起来像这样:(function( window, undefined ){ })(window); ……你是说undefined=1现在的值是未定义吗? - JaPerk14
@JaPerk14,请检查更新后的答案,我引用了文章中的一些内容,为了更深入地理解,建议您阅读整篇文章。 - Prasenjit Kumar Nag
@JaPerk14,如果你在全局作用域中有一个 undefined = 1;,那么如果你不使用 (function( window, undefined ){ })(window);,那么在该函数内部,undefined 的值也将为 1(因为你改变了全局的 undefined 变量)。这是不可取的,因为 undefined 应该是 undefined。因此,为了确保在函数内部使用 pattern - Prasenjit Kumar Nag

3

Undefined 是一种数据类型,但也是一个全局变量。

你可以创建一个模块来覆盖 undefined 的值:undefined = something

实际上,undefined 在这里是一个函数的未定义参数,它包装了整个代码:

(function(window, undefined) {
    // undefined is the undefined parameter
}(window)); 

这是安全的,因为undefined参数在局部作用域中,除了此函数中的代码以外,没有人可以对其进行赋值。

在定义匿名函数时,不必使用undefined作为参数。

如果你看到上面的函数,你会注意到它希望有两个参数,但只提供了一个

为什么需要还原undefined

因为要确保在花括号之间的作用域中undefined确实是undefined,即使有人在全局作用域中写入undefined = "defined";,因为undefined实际上可以被重新定义。

所以如果你有像下面这样的东西

var undefined = 1;

(function(window, undefined) {
  console.log(undefined); // output will be undefined not 1
}(window));

你只需要恢复undefined的原因,其他答案已经解释了。 - Luceos

2

jQuery通过不向该参数传递参数来确保其作用域内的undefined确实未定义。

例如,当undefined实际上并未被定义时,请参考以下代码:

var undefined = 1;
alert(undefined); // 1

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