问题描述
我在测试中看到了这个问题,其中没有声明变量 myObj,并要求根据以下 if 语句选择正确答案。
function myFunction() {
if(typeof myObj !== "undefined" && myObj !== null) {
a = 1
}
}
result: "undefined"
function myFunction() {
if(myObj !== null && typeof myObj !== "undefined") {
a = 1
}
}
result: Uncaught ReferenceError: myObj is not defined
我的问题是如果变量未定义,与“未定义”不一样,如果我想测试“未定义”值,我可以使用“null”来检查它是否未定义(例如 myObj === null),那么为什么第一个函数返回 undefined 而第二个返回 myObj 没有定义?
解决方法
有几件事正在发生:
-
值检查与类型检查不同。
如果您尝试读取不存在的标识符的值,则会出现错误。因此,如果
myObj === null
不存在(从未声明或以其他方式创建标识符),则myObj
会导致错误。但是在不存在的标识符上使用
typeof
会导致"undefined"
,没有错误。所以当typeof myObj
不存在时"undefined"
是myObj
。您可以在 the specification 中看到这一点:2(a) 如果 IsUnresolvableReference(val) 为真,则返回“未定义”。
-
&&
运算符短路。&&
评估它的第一个操作数,如果该值是假的,¹ 将假值作为其结果,对第二个操作数不做任何处理。但是,如果第一个操作数的值为真,&&
会评估第二个操作数并将该值作为结果。
由于这两件事,if(typeof myObj !== "undefined" && myObj !== null) {
可以正常工作,因为它首先执行 typeof myObj !== "undefined"
,并且由于 false
不存在时该值为 myObj
,因此结果&&
操作是 true
并且永远不会评估第二个操作数。但是 if(myObj !== null && typeof myObj !== "undefined") {
首先执行 myObj !== null
,尝试使用不存在的标识符的值,从而导致错误。
我的问题是如果一个变量没有定义,那是不是和“未定义”一样
不是在一般情况下,不是。 typeof
很特别。对不存在的标识符所做的任何其他事情都会引发错误。 (好吧,还有一件事:在松散模式下,如果您分配给一个不存在的标识符,它会创建一个全局标识符。这就是我所说的 The Horror of Implicit Globals,也是使用 {{ 3}},这是它一直应该出现的错误。)
¹ “truthy”和“falsy”是我们在 JavaScript 中使用的术语,用于指代强制为 true
的值和用作条件时强制为 false
的值。有一组固定的假值:0
、""
、NaN
、null
、undefined
,当然还有 false
(也document.all
在浏览器中;奇怪但真实)。所有其他值都是真实的。
问题在于你对 JavaScript 中 && 运算符的理解,
举例说明:expr1 && expr2
如果expr1可以转换为true,则返回expr2;否则,返回 expr1。
在你的第一种情况下:
typeof myObj !== "undefined" // 这是错误的,因为 typeof myObj 是未定义的
所以它返回 undefined。
在你的第二种情况下: myObj !== "null" // 这给出了 Uncaught ReferenceError: myobj is not defined,as this is 不正确,返回同样的错误