JavaScript: undefined !== undefined?

70

注意:根据ECMAScript5.1,第15.1.1.3节,window.undefined是只读的。

  • 现代浏览器正确实现了这个。例如:Safari 5.1,Firefox 7,Chrome 20等。
  • 在以下浏览器中,undefined仍然可以更改:Chrome 14,...

最近我将Facebook ConnectTersus集成时,当尝试调用Facebook API函数时,最初收到错误消息Invalid Enumeration ValueHandler already exists

结果发现问题的原因是

object.x === undefined

当'object'中没有属性'x'时,返回false。

我通过在两个Facebook函数中将严格相等性替换为常规相等性来解决了这个问题:

FB.Sys.isUndefined = function(o) { return o == undefined;};
FB.Sys.containsKey = function(d, key) { return d[key] != undefined;};

这对我有用,但似乎暗示着Facebook的JavaScript代码和我的代码之间存在某种冲突。
是什么导致了这个问题?
提示:文档中充分说明undefined == null,而undefined !== null。这不是问题所在。问题是为什么我们得到undefined !== undefined

5
有趣,我刚刚在控制台中尝试过了。var a = {}; a.b === undefined //true。你确定你的object.x === undefined返回假是因为对象中没有x字段吗? - Grace Huang
1
根据ECMAScript5.1第15.1.1.3节,window.undefined是只读的。真是太好了,因为在以前的版本中,有人可以全局覆盖undefined,这会导致所有东西都崩溃:( - Dan
window.undefined只读之前,void(0)被认为是获取未定义值的标准超安全方式,如果您不想信任环境的undefined变量。MDN - snarf
7个回答

92

问题在于使用 == 进行比较时,undefined 与 null 相比较会得到 true。

因此通常检测 undefined 的方法如下:

typeof x == "undefined"

这可以确保变量的类型真正是undefined。


61
在这里,许多回答中最大的误解是认为'undefined'是JavaScript关键字。实际上它根本不是一个关键字,而是一个变量,大部分情况下该变量的值是未定义的。因此,“somevar === undefined”只有在确实未定义'undefined'变量时才有效。我曾经看到过一些代码(jcanvas),其中类包装函数包括一个名为“undefined”的最后参数(但从未使用),仅仅是为了确保函数范围内存在一个名为“undefined”的未定义变量。除了这种特殊情况之外,使用'typeof'是唯一正确的方式。 - Scott Lahteine
2
这是否意味着,只要未定义,我也可以使用“garglblarg”作为代替? - Dercsár
1
@Dercsár:是的,var foo; foo === undefined // true - pimvdb
3
实际上,那不是真的。undefined 不是一个关键字,但它是 JavaScript 中的内置对象。引用实际上未定义的内容会引发 ReferenceError: whatever is not defined 错误。 - fletom
1
有人能解释一下为什么 myVar === undefined 会引发 ReferenceError,而 this.myVar === undefined 却不会(只是返回 true)吗?附注:myVar 从未被定义过。 - MaksymB
显示剩余4条评论

64

事实证明,你可以将window.undefined设置为任何值,并在object.x是真正的undefined时得到object.x !== undefined。在我的情况下,我无意中将undefined设置为null。

最容易看到这种情况发生的方法是:

window.undefined = null;
alert(window.xyzw === undefined); // shows false

当然,这不太可能发生。在我这种情况下,bug有点微妙,并等同于以下情况。

var n = window.someName; // someName expected to be set but is actually undefined
window[n]=null; // I thought I was clearing the old value but was actually changing window.undefined to null
alert(window.xyzw === undefined); // shows false

18
啊哈!这正是我反对使用未定义属性(而不是使用 typeof)的主要原因。祝贺你解决了这个错误。+1 - annakata
2
始终为对象命名空间的另一个原因是... 如果你写成了var n = blah.someName; blah[n]=null; 那么就可以避免出现错误。 - cmcculloh
2
现代浏览器中无法覆盖它。 - Memke

19

我想发布一些关于undefined的重要信息,这可能是初学者不知道的。

看下面的代码:

 /* 
  * Consider there is no code above. 
  * The browser runs these lines only.
  */

   // var a;  
   // --- commented out to point that we've forgotten to declare `a` variable 

   if ( a === undefined ) {
       alert('Not defined');
   } else {
       alert('Defined: ' + a);
   }

   alert('Doing important job below');

如果您使用var运行此代码,其中变量a从未被声明, 你会得到一个错误异常并且完全没有警报。
相反,你的脚本将意外地终止,并在第一行上抛出未处理的异常。
这是唯一可以通过使用typeof关键字来检查undefined的可靠方法,该关键字专为此目的设计:
   /* 
    * Correct and safe way of checking for `undefined`: 
    */

   if ( typeof a === 'undefined' ) {
       alert(
           'The variable is not declared in this scope, \n' +
           'or you are pointing to unexisting property, \n' +
           'or no value has been set yet to the variable, \n' + 
           'or the value set was `undefined`. \n' +
           '(two last cases are equivalent, don\'t worry if it blows out your mind.'
           );
   }

   /* 
    *  Use `typeof` for checking things like that
    */

这种方法在所有情况下都有效。

使用它的最后一个参数是,早期版本的Javascript中可能会覆盖undefined

     /* @ Trollface @ */
        undefined = 2;
     /* Happy debuging! */  

Hope I was clear enough.


函数xx(a) { 如果(a === undefined) a = 'default'; }xx() - 这是在JavaScript中安排默认参数的好方法 - Dan

14

使用==等于运算符而不是===是一种不好的做法。

undefined === undefined // true
null == undefined // true
null === undefined // false

如果x是未知属性,object.x === undefined应该返回true

在《JavaScript: The Good Parts》的Bad Parts章节中,Crockford写道:

If you attempt to extract a value from an object, and if the object does not have a member with that name, it returns the undefined value instead.

In addition to undefined, JavaScript has a similar value called null. They are so similar that == thinks they are equal. That confuses some programmers into thinking that they are interchangeable, leading to code like

value = myObject[name];
if (value == null) {
    alert(name + ' not found.');
}

It is comparing the wrong value with the wrong operator. This code works because it contains two errors that cancel each other out. That is a crazy way to program. It is better written like this:

value = myObject[name];
if (value === undefined) {
    alert(name + ' not found.');
}

你曾经读过这篇精彩的文章吗:http://webreflection.blogspot.ie/2010/10/javascript-coercion-demystified.html? - op1ekun
1
"(value == null)"通常是一种完全合理且有效的比较方式。您有多少次实际上需要区分未定义和明确的空值是很少关注它不存在的原因。 - snarf

11

来自 - JQuery核心样式指南

  • 全局变量:
    typeof variable === "undefined"

  • 局部变量:
    variable === undefined

  • 属性:
    object.prop === undefined


1
只是一个提醒 - 如果变量根本不存在,那么它既不是局部的也不是全局的。不太直观的是,我们应该像在 Dan 的示例中展示的那样检查那些可能不存在的变量,就像我们检查全局变量一样。 - JustAMartin

4
var a;

typeof a === 'undefined'; // true
a === undefined; // true
typeof a === typeof undefined; // true
typeof a === typeof sdfuwehflj; // true

2

A). 我从未相信并且永远不会信任那种声称可以在用户不编码的情况下生成代码的工具,当它是一个图形化工具时,我更不信任。

B). 对于Facebook Connect,我从未遇到过问题。它仍然是在浏览器中运行的普通JavaScript代码,无论你在哪里,undefined===undefined

简而言之,你需要提供证据表明你的object.x确实是undefined而不是null或其他值,因为我认为你所描述的情况是不可能发生的 - 无意冒犯 :) - 我敢肯定问题存在于Tersus代码中。


1
谢谢,annakata。你持怀疑态度的回答促使我重新审视了这个问题并找到了正确的答案(见下文)。 - Youval Bronicki

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