在自调用函数中不可变的未定义

Immutable undefined in self invoking functions

本文关键字:不可变 未定义 函数 调用      更新时间:2023-09-26

自从 ECMAScript 5 问世以来已经有一段时间了,并且在大多数现代浏览器(IE9、CH 19+、FF 4+)中得到了很好的支持,随之而来的是"不可变的未定义"。虽然我一直看到"未定义"是这样传递的:

(function ( ..., undefined ) {
})(...);

据我所知,Crockford的JSLint工具并不真正喜欢它:

Expected an identifier and instead saw 'undefined' (a reserved word).

即使它没有被传递(函数调用上没有参数),它实际上是一个标识符。我知道他的工具不是我们应该遵循的圣经,另一方面,JSHint似乎并不关心它。

这在今天是否仍被认为是最佳实践,它如何影响代码性能/安全性?考虑浏览器支持>= IE9。

这在今天是否仍被认为是最佳实践,它如何影响代码性能/安全性?考虑浏览器支持>= IE9。

undefined非常相似,Infinity是全局对象的不可写属性,而不是像null那样的文字,因此它可以用作参数名而不会引发错误。让我们考虑这样的函数

function example(Infinity) {
    return Infinity;
}

example中,Infinity不再是一个不可写的属性,而是像函数的任何其他参数一样,如果没有传递任何参数,则初始化为undefined,或者以其他方式获取参数的值。这意味着在这个函数中,你不能只假设Infinity意味着无穷大,因为它没有,但你可以假设它意味着undefined

因此,让我们回到undefined的问题。它将被初始化为 undefined 因此含义将保持不变,但是,它现在已经失去了函数中的不变性,因此任何将值断言为 undefined 的拼写错误都将延续此错误。此外,如果将参数传递给函数,则值将与开始时不同。

因此,总而言之,它确实对安全性有影响,因为像这样的undefined不再那么"安全",因为它已经失去了不可变的状态并且可以更改。


值得注意的是,undefined实际上并不是一个保留字。如果您需要一个兼容性undefined,而不是将其添加为参数名称,我建议在函数顶部或全局命名空间中使用一个简单的var undefined;,您可以在全局命名空间中找到var undefined; undefined = 1; undefined; // undefined它是不可变的。

如果你想

遵守jsLint,你可以使用另一个不是保留字的变量而不是undefined。以下内容符合 jsLint:

(function (window, document, undef) {
    'use strict';
}(window, document));

但是,您需要记住使用新定义的变量(在本例中为undef而不是undefined)。添加上述严格模式是为了符合 jsLint。这主要用于确定您正在测试的未定义的变量实际上是未定义的。

请注意,如果您在 jsLint 网站上提供的文本区域中运行此示例,则可能需要定义 windowdocument 。在我这样做之前,我收到了两个错误。

var window = window; //global window object
var document = document; //global window object

但是,我认为:

(function (..., undefined) {
    'use strict';
}(...));

完全没问题,更重要的是,强烈推荐。

在某些情况下,保留字可以从其正常状态更改。例如将undefined设置为true。保罗·爱尔兰在他的视频中简要讨论了这个问题: http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/