每次有人提到针对undefined
进行测试时,都会指出undefined
不是关键字,因此可以设置为"hello"
,因此您应该改用typeof x == "undefined"
。这对我来说似乎很荒谬。没有人会这样做,如果他们这样做了,就有足够的理由永远不使用他们编写的任何代码......右?
我发现了一个不小心将undefined
设置为 null
的例子,这是为了避免假设undefined
没有被覆盖的原因。但是如果他们这样做了,这个错误就不会被发现,我看不出这有什么好。
在C++每个人都很清楚说#define true false
是合法的,但没有人建议你避免true
而改用0 == 0
。你只是假设没有人会成为一个足够大的混蛋来做到这一点,如果他们这样做了,就再也不相信他们的代码了。
这是否曾经真正咬过其他人分配给undefined
的人(故意(并且它破坏了您的代码,或者这更像是一种假设的威胁?我愿意冒险让我的代码更具可读性。这真的是一个坏主意吗?
重申一下,我不是在问如何防止重新分配的未定义。这些技巧我已经写了100次了。我问不使用这些技巧有多危险。
不,我从来没有。这主要是因为我在现代浏览器上开发,这些浏览器大多符合 ECMAScript 5。ES5 标准规定undefined
现在是只读的。如果您使用严格模式(您应该使用(,如果您不小心尝试修改它,将引发错误。
undefined = 5;
alert(undefined); // still undefined
'use strict';
undefined = 5; // throws TypeError
您不应该做的是创建自己的作用域、可变undefined
:
(function (undefined) {
// don't do this, because now `undefined` can be changed
undefined = 5;
})();
常数很好。仍然没有必要,但很好。
(function () {
const undefined = void 0;
})();
没有适当的代码可以做这样的事情。但是你永远无法知道一些想要聪明的开发人员或你正在使用的插件/库/脚本做了什么。另一方面,这是极不可能的,现代浏览器根本不允许覆盖undefined
,所以如果你使用这样的浏览器进行开发,你会很快注意到是否有任何代码试图覆盖它。
即使你没有要求它 - 许多人在寻找更常见的"如何防止重新定义undefined
"问题时可能会发现这个问题,所以我无论如何都会回答:
浏览器有多旧,都有一种非常好的方法可以获得真正未定义的undefined
:
(function(undefined) {
// your code where undefined is undefined
})();
这是有效的,因为未指定的参数始终undefined
。你也可以使用一个接受一些真实参数的函数来做到这一点,例如,当你使用 jQuery 时,就像这样。通常,以这种方式确保环境正常是一个好主意:
(function($, window, undefined) {
// your code where undefined is undefined
})(jQuery, this);
然后,您可以确定在该匿名函数中,以下情况是正确的:
-
$ === jQuery
-
window === [the global object]
-
undefined === [undefined]
.
但是,请注意,有时typeof x === 'undefined'
实际上是必要的:如果变量x
从未设置为值(与设置为 undefined
相反(,则以不同的方式读取x
,例如 if(x === undefined)
将引发错误。但这不适用于对象属性,因此如果您知道y
始终是一个对象,那么if(y.x === undefined)
是完全安全的。
有一个简单的解决方案:与始终未定义的void 0
进行比较。
请注意,应避免使用==
,因为它可能会强制使用值。请改用===
(和!==
(。
也就是说,如果有人在将某些内容与undefined
进行比较时编写=
而不是==
,则可能会错误地设置未定义的变量。
只有你知道你使用什么代码,因此它有多危险。这个问题不能以你澄清你想要回答的方式回答。
1(创建一个团队策略,不允许重新定义undefined,将其保留给更流行的使用。扫描现有代码以查找未定义的左分配。
2(如果你不能控制所有的场景,如果你的代码是在你或你的策略控制的情况下使用的,那么显然你的答案是不同的。扫描使用脚本的代码。哎呀,如果您愿意,可以扫描网络以获取未定义的左分配的统计信息,但我怀疑这已经为您完成了,因为在这里追求答案 #1 或 #3 更容易。
3(如果这个答案还不够好,那可能是因为,同样,你需要一个不同的答案。也许您正在编写一个将在公司防火墙中使用的流行库,并且您无权访问调用代码。然后在这里使用其他很好的答案之一。请注意流行的jQuery库实践声音封装,并开始:
(function( window, undefined ) {
只有你能以你所寻求的特定方式回答你的问题。还有什么好说的?
编辑:附言如果你真的想要我的意见,我会告诉你这根本不危险。 任何可能导致缺陷的东西(例如分配给未定义,这显然是一种有据可查的危险行为(本身就是缺陷。缺陷就是风险。但这只是在我的场景中,我可以持有这种观点。正如我推荐的那样,我回答了我的用例的问题。
针对未定义进行测试是安全的。正如你已经提到的。如果你得到一些覆盖它的代码(这是高度可改进的(,就不要再使用它了。
也许如果您正在创建一个供公共使用的库,您可以使用一些技术来避免用户更改它。但即使在这种情况下,这也是他们的问题,而不是你的图书馆。
在为 ECMAScript 5.1 的浏览器编码时,您可以在代码中使用 undefined
,因为根据语言规范,它是不可变的。
另请参阅此兼容性表或此 caniuse ECMAScript 5 以查看所有现代浏览器 (IE 9+( 都实现了不可变undefined
。
一点也不危险。它只能在 ES3 引擎上运行时被覆盖,并且不太可能再使用。
首先,如果你的代码坏了,那可能不是因为其他开发人员"试图成为一个混蛋",正如你所说的那样。
确实,undefined
不是关键字。但它是全局级别的原语。它打算像这样使用(请参阅 developer.mozilla.org 中的"未定义"(:
var x;
if (x === undefined) {
// these statements execute
}
else {
// these statements do not execute
}
常见的替代方案(也来自 MDN(,在我看来更好的方法是:
// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
// these statements execute
}
if(x === undefined){ // throws a ReferenceError
}
这有几个优点,明显的一个(来自注释(是当 x 未声明时它不会触发异常。同样值得注意的是,MDN 还指出,在第一种情况下使用 ===
而不是 ==
很重要,因为:
var x=null;
if (x === undefined) {
// this is probably what you meant to do
// these lines will not execute in this case
}
else if (x == undefined) {
// these statements will execute even though x *is* defined (as null)
}
else {
// these statements do not execute
}
这是另一个经常被忽视的原因,为什么在所有情况下只使用第二种选择可能更好。
结论:以第一种方式编写代码并没有错,当然也不危险。您看到的用作反对它的示例的论点(它可以被覆盖(并不是使用 typeof
编写替代方案的最有力论据。但是使用 typeof
更强大,具体原因之一是:当您的 var 未声明时,它不会引发异常。也可以说,使用==
而不是===
是一个常见的错误,在这种情况下,它没有按照您的预期进行操作。那么为什么不使用typeof
呢?