为什么 Javascript 中的未定义变量有时会评估为 false,有时会抛出未捕获的 ReferenceError?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9981104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does an undefined variable in Javascript sometimes evaluate to false and sometimes throw an uncaught ReferenceError?
提问by Gullbyrd
Everything I've ever read indicates that in Javascript, the boolean value of an undefined variable is False. I've used code like this hundreds of times:
我读过的所有内容都表明,在 Javascript 中,未定义变量的布尔值是 False。我已经使用过数百次这样的代码:
if (!elem) {
...
}
with the intent that if "elem" is undefined, the code in the block will execute. It usually works, but on occasion the browser will throw an error complaining about the undefined reference. This seems so basic, but I can't find the answer.
目的是如果未定义“elem”,则块中的代码将执行。它通常有效,但有时浏览器会抛出错误,抱怨未定义的引用。这看起来很基本,但我找不到答案。
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined? That seems completely unintuitive.
未定义的变量与已定义但值为 undefined 的变量之间是否存在差异?这似乎完全不直观。
回答by Jon
What is a ReferenceError?
什么是引用错误?
As defined by ECMAScript 5, a ReferenceError
indicates that an invalid reference has been detected. That doesn't say much by itself, so let's dig a little deeper.
根据 ECMAScript 5 的定义,aReferenceError
表示检测到无效引用。这本身并不能说明什么,所以让我们深入挖掘一下。
Leaving aside strict mode, a ReferenceError
occurs when the scripting engine is instructed to get the value of a reference that it cannot resolve the base valuefor:
撇开严格模式不谈,ReferenceError
当指示脚本引擎获取无法解析其基值的引用值时,会发生 a :
A Reference is a resolved name binding. A Reference consists of three components, the base value, the referenced name and the Boolean valued strict reference flag. The base value is either undefined, an Object, a Boolean, a String, a Number, or an environment record (10.2.1). A base value of undefined indicates that the reference could not be resolved to a binding. The referenced name is a String.
引用是解析的名称绑定。引用由三个部分组成,基值、引用名称和布尔值严格引用标志。基值是未定义的、对象、布尔值、字符串、数字或环境记录 (10.2.1)。未定义的基值表示无法将引用解析为绑定。引用的名称是一个字符串。
When we are referencing a property, the base value is the object whose property we are referencing. When we are referencing a variable, the base value is unique for each execution context and it's called an environment record. When we reference something that is neither a property of the base object value nor a variable of the base environment record value, a ReferenceError
occurs.
当我们引用一个属性时,基值是我们引用其属性的对象。当我们引用一个变量时,每个执行上下文的基值都是唯一的,它被称为环境记录。当我们引用既不是基础对象值的属性也不是基础环境记录值的变量的东西时,ReferenceError
就会发生a 。
Consider what happens when you type foo
in the console when no such variable exists: you get a ReferenceError
because the base valueis not resolvable. However, if you do var foo; foo.bar
then you get a TypeError
instead of a ReferenceError
-- a subtle perhaps but very significant difference. This is because the base valuewas successfully resolved; however, it was of type undefined
, and undefined
does not have a property bar
.
想想,当你键入的内容会发生foo
在当没有这样的变量存在控制台:你得到一个ReferenceError
,因为基值是无法解析。然而,如果你这样做了,var foo; foo.bar
那么你会得到一个TypeError
而不是一个ReferenceError
——一个微妙的也许但非常重要的差异。这是因为基值被成功解析;但是,它的类型为undefined
,并且undefined
没有属性bar
。
Guarding against ReferenceError
防范 ReferenceError
From the above it follows that to catch a ReferenceError before it occurs you have to make sure that the base value is resolvable. So if you want to check if foo
is resolvable, do
从上面可以看出,要在 ReferenceError 发生之前捕获它,您必须确保基值是可解析的。因此,如果您想检查是否foo
可解析,请执行
if(this.foo) //...
In the global context, this
equals the window
object so doing if (window.foo)
is equivalent. In other execution contexts it does not make as much sense to use such a check because by definition it's an execution context your own code has created -- so you should be aware of which variables exist and which do not.
在全局上下文中,this
equalswindow
对象这样做if (window.foo)
是等效的。在其他执行上下文中,使用这样的检查没有多大意义,因为根据定义,它是您自己的代码创建的执行上下文——因此您应该知道哪些变量存在,哪些不存在。
回答by Kris
Checking for undefined works for variables that have no value associated but if the variable itself hasn't been declared you can run into these reference issues.
检查 undefined 适用于没有关联值的变量,但如果变量本身尚未声明,您可能会遇到这些引用问题。
if (typeof elem === "undefined")
This is a far better check as doesn't run the risk of the reference issue as typeof isn't a method but a keyword within JavaScript.
这是一个更好的检查,因为不会冒引用问题的风险,因为 typeof 不是一个方法,而是 JavaScript 中的一个关键字。
回答by Matt
Is it that there's a difference between a variable that has not been defined and one that has been defined but which has a value of undefined?
未定义的变量与已定义但值为 undefined 的变量之间是否存在差异?
Yes. A undeclared variable will throw a ReferenceError
when used in an expression, which is what you're seeing.
是的。未声明的变量ReferenceError
在表达式中使用时会抛出 a ,这就是您所看到的。
if (x) { // error, x is undeclared
}
Compared to;
相比;
var y; // alert(y === undefined); // true
if (y) { // false, but no error
}
That seems completely unintuitive.
这似乎完全不直观。
Meh... what I find unintuitive:
咩......我觉得不直观:
if (y) // error, y is undeclared
var x = {};
if (x.someUndeclaredAttribute) // no error... someUndeclaredAttribute is implictly undefined.
回答by mathieu
回答by A.com
undefined = variable exists but has no value in it
undefined = 变量存在但没有值
ReferenceError = variable does not exist
ReferenceError = 变量不存在
回答by tim
or you use try/catch:
或者你使用 try/catch:
try { x } catch(err){}
This way you're not doing anything in case of an error but at least your script won't jump off the cliff...
这样你就不会在出现错误的情况下做任何事情,但至少你的脚本不会跳下悬崖......
回答by Pointy
In strict mode, it is an error:
在严格模式下,是一个错误:
function a() {
"use strict";
if (!banana) alert("no banana"); // throws error
}
It's always really been better to make an explicit test for globals:
对全局变量进行显式测试总是更好:
if (!window['banana']) alert("no banana");
It doesn't make sense to perform such a test for non-global variables. (That is, testing to see whether the variable is defined that way; it's fine to test to see whether a defined variable has a truthy value.)
对非全局变量执行这样的测试是没有意义的。(也就是说,测试以查看变量是否以这种方式定义;测试以查看定义的变量是否具有真值也可以。)
editI'll soften that to say that it rarelymakes sense to thusly test for the existence of non-globals.
编辑我会软化这一点,说这样测试非全局变量的存在很少有意义。
回答by Xie
When a variable is declared and not initialized or it's used with declaration, its value is "undefined". The browser complains exactly when this undefined variable is referenced. Here "reference" means some piece of javascript code is trying to visit an attribute or method of it. For example, if "elem" is undefined, this will throw an exception:
当变量已声明但未初始化或与声明一起使用时,其值为“未定义”。当引用这个未定义的变量时,浏览器会准确地抱怨。这里的“引用”意味着一些 javascript 代码正在尝试访问它的属性或方法。例如,如果“elem”未定义,则会抛出异常:
elem.id = "BadElem";