为什么Javascript中的未定义变量有时会被评估为false,有时会抛出未被捕获的ReferenceError?

时间:2012-04-02 17:42:39

标签: javascript

我读过的所有内容都表明在Javascript中,未定义变量的布尔值为False。我已经使用过这样的代码数百次了:

if (!elem) {
   ...
}

意图是如果未定义“elem”,则执行块中的代码。它通常有效,但有时浏览器会抛出一个抱怨未定义引用的错误。这看起来很基本,但我找不到答案。

是否存在尚未定义的变量与已定义但具有未定义值的变量之间存在差异?这似乎完全不直观。

8 个答案:

答案 0 :(得分:29)

什么是ReferenceError?

根据ECMAScript 5的定义,ReferenceError表示检测到无效引用。这本身并不多说,所以让我们深入挖掘一下。

除了严格模式外,当指示脚本引擎获取cannot resolve the base value的引用值时,会出现ReferenceError

  

参考是已解析的名称绑定。参考文献由三个组成   组件,基值,引用的名称和布尔值   严格的参考标志。基值是未定义的,对象,   布尔值,字符串,数字或环境记录(10.2.1)。一个   undefined的基值表示引用不能   解决了绑定问题。引用的名称是String。

当我们引用属性时,基值是我们引用其属性的对象。当我们引用变量时,基值对于每个执行上下文都是唯一的,它被称为环境记录。当我们引用既不是基础对象值的属性也不是基础环境记录值的变量的东西时,会发生ReferenceError

考虑在没有此类变量的情况下在控制台中键入foo时会发生什么:您得到ReferenceError,因为基值 无法解析。但是,如果您执行var foo; foo.bar,则会得到TypeError而不是ReferenceError - 这可能是一个微妙但非常显着的差异。这是因为基值已成功解决;但是,它的类型为undefinedundefined没有属性bar

防范ReferenceError

从上面可以看出,为了在它发生之前捕获一个ReferenceError,你必须确保基值是可解析的。因此,如果您想检查foo是否可解析,请执行

if(this.foo) //...

在全局上下文中,this等于window对象,因此if (window.foo)是等效的。在其他执行上下文中,使用这样的检查没有多大意义,因为根据定义,它是您自己的代码创建的执行上下文 - 因此您应该知道哪些变量存在而哪些不存在。

答案 1 :(得分:6)

为没有关联值的变量检查未定义的工作但如果变量本身尚未声明,则可能会遇到这些引用问题。

if (typeof elem === "undefined")

这是一个更好的检查,因为不会冒引用问题的风险,因为typeof不是方法,而是JavaScript中的关键字。

答案 2 :(得分:4)

  

是否存在尚未定义的变量与已定义但具有未定义值的变量之间存在差异?

即可。未声明的变量在表达式中使用时会抛出ReferenceError,这就是您所看到的。

if (x) { // error, x is undeclared

}

与;相比;

var y; // alert(y === undefined); // true

if (y) { // false, but no error

}
  

这似乎完全不直观。

Meh ......我觉得不直观:

if (y) // error, y is undeclared

var x = {};

if (x.someUndeclaredAttribute) // no error... someUndeclaredAttribute is implictly undefined.

答案 3 :(得分:2)

以下是关于环境记录的Jon's解释示例:

var bar = function bar() {
    if (!b) { // will throw a reference error.
    }
},
foo = function foo() {
    var a = false;

    if (a) {
        var b = true;
    }

    if (!b) { // will not throw a reference error.
    }
};

答案 4 :(得分:0)

在严格模式下,这是一个错误:

function a() {
  "use strict";
  if (!banana) alert("no banana"); // throws error
}

对全局变量进行显式测试总是更好:

if (!window['banana']) alert("no banana");

对非全局变量执行此类测试没有意义。 (也就是说,测试变量是否以这种方式定义;测试以查看定义的变量是否具有真值是可以的。)

编辑我会软化它,说很少有意义地测试非全局变量的存在。

答案 5 :(得分:0)

当一个变量被声明并且没有被初始化或者它与声明一起使用时,它的值是“未定义的”。浏览器会在引用此未定义变量时提出建议。这里的“引用”意味着某些javascript代码试图访问它的属性或方法。例如,如果未定义“elem”,则会抛出异常:

elem.id = "BadElem";

答案 6 :(得分:0)

或者您使用try / catch:

try { x } catch(err){}

这样一来,如果出现错误,你就不会做任何事情,但至少你的剧本不会跳出悬崖......

答案 7 :(得分:0)

undefined =变量存在但没有值

ReferenceError =变量不存在