我们经常在JavaScript代码中使用以下代码模式
if (typeof(some_variable) != 'undefined' && some_variable != null)
{
// Do something with some_variable
}
是否有一种不那么冗长的检查方法具有相同的效果?
根据一些论坛和文献,简单地说下面应该有同样的效果。
if (some_variable)
{
// Do something with some_variable
}
不幸的是,当some_variable未定义时,Firebug在运行时将这样的语句计算为错误,而第一个语句对它来说很好。这仅仅是Firebug的一种(不必要的)行为,还是这两种方式之间真的有一些区别?
为了理解,让我们分析一下Javascript引擎在转换undefined、null和”(也是一个空字符串)时返回的值是什么。您可以直接在开发人员控制台检查相同的内容。
你可以看到所有都被转换为false,这意味着所有这三个都是通过javascript假设“缺乏存在”。因此,您不需要像下面这样显式地检查代码中的所有三个。
if (a === undefined || a === null || a==='') {
console.log("Nothing");
} else {
console.log("Something");
}
我还想指出一件事。
布尔(0)的结果是什么?
当然是假的。当0是预期结果中的有效值时,这将在代码中创建一个错误。所以在写代码的时候一定要检查这个。
首先,你必须清楚你要测试什么。JavaScript有各种各样的隐式转换会让您出错,还有两种不同类型的相等比较器:==和===。
测试null或未定义的函数test(val)应具有以下特征:
test(null) => true
test(undefined) => true
test(0) => false
test(1) => false
test(true) => false
test(false) => false
test('s') => false
test([]) => false
让我们来看看哪些想法实际上通过了我们的测试。
这些工作:
val == null
val === null || val === undefined
typeof(val) == 'undefined' || val == null
typeof(val) === 'undefined' || val === null
这些都不起作用:
typeof(val) === 'undefined'
!!val
我创建了一个jsperf条目来比较这些方法的正确性和性能。目前的结果还不确定,因为在不同的浏览器/平台上还没有足够的运行。请花一分钟在你的电脑上运行测试!
目前,简单的val == null测试似乎提供了最好的性能。它也是最短的。如果您想要补码,测试可以被反求为val != null。
这是一个非常罕见的例子,建议使用==而不是===。表达式somevar == null对于undefined和null将返回true,但对于其他所有内容将返回false(如果变量未声明则会出现错误)。
如预期的那样,使用!=将翻转结果。
现代编辑器不会对使用==或!=操作符加null发出警告,因为这几乎总是需要的行为。
最常见的比较:
undeffinedVar == null // true
obj.undefinedProp == null // true
null == null // true
0 == null // false
'0' == null // false
'' == null // false
自己试试吧:
let undefinedVar;
console.table([
{ test : undefinedVar, result: undefinedVar == null },
{ test : {}.undefinedProp, result: {}.undefinedProp == null },
{ test : null, result: null == null },
{ test : false, result: false == null },
{ test : 0, result: 0 == null },
{ test : '', result: '' == null },
{ test : '0', result: '0' == null },
]);
如果您试图引用一个未声明的变量,那么在所有JavaScript实现中都会抛出一个错误。
对象的属性不受相同条件的约束。如果未定义对象属性,则在尝试访问它时不会抛出错误。在这种情况下,你可以缩短:
if (typeof(myObj.some_property) != "undefined" && myObj.some_property != null)
to
if (myObj.some_property != null)
考虑到这一点,以及全局变量可以作为全局对象(浏览器中的窗口)的属性访问的事实,你可以对全局变量使用以下方法:
if (window.some_variable != null) {
// Do something with some_variable
}
在局部作用域中,确保变量在代码块的顶部声明总是有用的,这将节省重复使用typeof。