JavaScript 空值检查

185

我遇到了以下代码:

function test(data) {
    if (data != null && data !== undefined) {
        // some code here
    }
}

我对JavaScript还比较陌生,但是从我在这里阅读的其他问题来看,我认为这段代码没有太多意义。


特别地,这个回答指出

如果您在typeof之外的任何上下文中访问未定义的变量,则会收到错误消息。

更新:上述答案的引用可能具有误导性。它应该说“一个未声明的变量”而不是“一个未定义的变量”

正如我在Ryan ♦maericsnwellnhof的回答中发现的那样,即使没有向函数提供参数,其参数变量也总是被声明的。这个事实也证明了下面列表中的第一项是错误的。


根据我的理解,可能会遇到以下情况:

  • 调用函数时没有传递参数,因此使data成为未定义变量,并在data != null上引发错误。

  • 函数被调用时明确使用null(或undefined)作为其参数,在这种情况下,data != null已经保护了内部代码,使&& data !== undefined无用。

  • 函数被调用时具有非空的参数,在这种情况下,它将平凡地通过data != nulldata !== undefined

问题:我的理解是正确的吗?


我在Firefox的控制台中尝试了以下内容:

--
[15:31:31.057] false != null
[15:31:31.061] true
--
[15:31:37.985] false !== undefined
[15:31:37.989] true
--
[15:32:59.934] null != null
[15:32:59.937] false
--
[15:33:05.221] undefined != null
[15:33:05.225] false
--
[15:35:12.231] "" != null
[15:35:12.235] true
--
[15:35:19.214] "" !== undefined
[15:35:19.218] true

我想不出在data != null后面 data !== undefined 有任何用处的情况。


9
只需使用 if (data)。这是一种记忆化的 JavaScript 检查 data 变量是否为真的方法。 undefinednull、false、0、空字符串、空数组和没有属性的对象都会被视为 false,其余则视为 true。 - J0HN
21
如果使用 if(data),意味着他不能将 false0 作为 data 的值传递。 - techfoobar
3
可能本意是 data !== null && data !== undefined,它等同于 data != null 也等同于 data != undefined。前者更明确地表达了这些条件,因此更受青睐,而后两种条件可能会忽略它们都在检查 nullundefined - zzzzBov
2
顺便提一下,对于“undefined”的显式测试,在我看来是一种代码坏味道。它不像“null”那样是受保护的关键字,而是一个恰好未定义的变量。这是完全有效的,但会破坏您的代码:undefined = 1 - Izkata
@J0HN Boolean({})Boolean([]) 都是 true。 - Jim Jones
显示剩余3条评论
8个回答

112
一个“未定义变量”与值undefined不同。
未定义变量:
var a;
alert(b); // ReferenceError: b is not defined
一个值为 undefined 的变量:
var a;
alert(a); // Alerts “undefined”
当函数接受参数时,即使该参数的值为undefined,也始终会声明该参数,因此不会出现任何错误。你说!= null后跟!== undefined是没有用的,这一点是正确的。

32
data !== null && data !== undefined是有意义的。 - bfavaretto
@bfavaretto:是的,可能实际上是个打字错误。但你永远不知道... :D - Ry-
1
正如我所想,感谢您的澄清。此外,我不认为这是一个打字错误。我在整个脚本中运行了查找和计数,它找到了10个出现次数,所以...我猜作者也需要对此进行澄清。 - afsantos
2
撤销我上面的评论:实际上,data != null会检查nullundefined(但有趣的是,只检查nullundefined,而不是其他假值)。 - bfavaretto

96

在JavaScript中,null是一个特殊的单例对象,用于表示“没有值”。您可以通过比较测试它,而且像在JavaScript中通常做的那样,使用===运算符是一个好习惯,可以避免混淆类型强制转换:

var a = null;
alert(a === null); // true

就像@rynah提到的那样,"undefined"在JavaScript中有点令人困惑。但是,测试typeof(x)是否为字符串"undefined"总是安全的,即使"x"没有被声明为变量:

alert(typeof(x) === 'undefined'); // true

此外,如果变量未初始化,它们可以具有“未定义的值”:

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

把所有东西都放在一起,你的支票应该长成这个样子:

if ((typeof(data) !== 'undefined') && (data !== null)) {
  // ...

然而,由于变量"data"始终被定义为正式的函数参数,使用"typeof"运算符是不必要的,您可以安全地直接与"未定义值"进行比较。

function(data) {
  if ((data !== undefined) && (data !== null)) {
    // ...

这段代码片段的意思是“如果函数被传入了一个已定义且不为null的参数…”


5
然而,为什么它应该看起来像这样?!= null将对除了nullundefined之外的所有值都为true,我们确定这个变量已经被声明。在其他情况下,typeof甚至可能很危险——如果您错拼变量名称会怎样?由于没有错误,这可能会长时间未被发现。 - Ry-
@maerics 如果我理解你的回答正确的话,在像上面的场景中进行空值检查时,您不会使用 !=,而只会使用严格比较 !==,对吗? - afsantos
@rynah:我不敢自认对 OP 的整体解决方案了解得足够多,以至于不知道是否适合进行空值测试,但我已经编辑过了,提到了使用“typeof”是不必要的事实。 - maerics
@maerics 当然,我同意这一点。只是为了额外的澄清,我在控制台中运行了更多的测试。似乎唯一会转换为null的值是undefinednull本身。运行undefined == null会得到true - afsantos
1
@Izkata:放弃任何试图重新定义 undefined 的库。而且,在 iPad 上使用 Safari 绝对不会这样做。你甚至无法删除 window.undefined - Ry-
显示剩余4条评论

22
在您的情况下,请使用data==null(仅对null和undefined为真 - 在第二张图片中请注意行/列为null-undefined)

function test(data) {
    if (data != null) {
        console.log('Data: ', data);
    }
}

test();          // the data=undefined
test(null);      // the data=null
test(undefined); // the data=undefined

test(0); 
test(false); 
test('something');

这里有所有的内容(源代码):

if

图片描述

==(其否定形式为!=

图片描述

===(其否定形式为!==

图片描述


8

问题:该函数未传递参数,因此将使数据成为未定义的变量,并在 data != null 时引发错误。

答案:是的,data 将被设置为未定义。请参见规范中的 第10.5节声明绑定实例化。但是访问未定义的值不会引发错误。您可能将其与在严格模式下访问未声明的变量引发错误混淆了。

问题:该函数特意使用 null(或 undefined)作为其参数进行调用,在这种情况下,data != null 已经保护了内部代码,使 && data !== undefined 无用。

问题:该函数使用非空参数进行调用,这将轻松通过 data != null 和 data !== undefined 两个测试。

答案:正确。请注意,以下测试是等效的:

data != null
data != undefined
data !== null && data !== undefined

请参见规范中的第11.9.3节 "抽象相等比较算法" 和第11.9.6节 "严格相等比较算法"。链接如下:第11.9.3节第11.9.6节

我并没有混淆未声明的变量,当没有提供参数时,我真的不知道它是如何工作的。我一直认为 data 根本不存在,而不是被设置为 undefined。我感谢您的澄清,并且这些参考资料帮助我更详细地了解了两种相等性是如何工作的。 - afsantos

3

我认为,通常情况下,测试变量不期望的值并不是一个好主意。因为这种测试可以被看作是编写禁止值黑名单。但是,如果你忘记列出所有禁止值怎么办?有人,甚至包括你自己,可以通过传递意外的值来破解你的代码。因此,更合适的方法是白名单 - 仅测试预期值而非意外值的变量。例如,如果你期望数据值是字符串,那么不要这样做:

function (data) {
  if (data != null && data !== undefined) {
    // some code here
    // but what if data === false?
    // or data === '' - empty string?
  }
}

做类似这样的事情:
function (data) {
  if (typeof data === 'string' && data.length) {
    // consume string here, it is here for sure
    // cleaner, it is obvious what type you expect
    // safer, less error prone due to implicit coercion
  } 
}

3

typeof foo === "undefined"foo === undefined不同,不要混淆。你真正需要的是typeof foo === "undefined"。另外,请使用!==代替!=

因此,该语句可以写为:

function (data) {
  if (typeof data !== "undefined" && data !== null) {
    // some code here
  }
}

编辑:

对于未声明的变量,您不能使用foo === undefined

var t1;

if(typeof t1 === "undefined")
{
  alert("cp1");
}

if(t1 === undefined)
{
  alert("cp2");
}

if(typeof t2 === "undefined")
{
  alert("cp3");
}

if(t2 === undefined) // fails as t2 is never declared
{
  alert("cp4");
}

1
好的,但在这种情况下变量已经声明了,那问题是什么? - Ry-
个人而言,我认为使用 foo === undefined 是很危险的。它会导致你的代码在试图避免的情况下失败。 - user2396441
我在谈论有关该函数的参数。另请参阅我的其他评论 - Ry-
1
为什么这个被踩了呢?第一句话是一个正确且重要的区分! - Izkata
1
@Izkata:因为初始陈述没有解释。在OP的情况下,foo === undefined是完全可接受的(假设未覆盖undefined)。该答案还未说明为什么应该使用!==代替!= - Matt

2
您可以简单地进行测试的方法是:
function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}

5
这个测试不是与上下文相关的吗?我的意思是,如果“data”参数的期望类型是字符串,在空字符串的情况下,这个测试返回false,这可能是适当的(函数可能想以某种方式处理空字符串)。 - afsantos
6
除非"data"的值为""0NaN(或其他类似的情况),否则该"if"块将被跳过,这可能或可能不是OP的意图。 - maerics
抱歉@afsantos,我没有看到你的评论。如果您想在数据未定义、为空或null时得到false,除非日期为空,您需要创建另一个*var toTest = data;,并在第一个测试后添加另一个测试,如下所示:if(toTest=="") { // some code here }*。 - Kadiri

-5
var a;
alert(a); //Value is undefined

var b = "Volvo"; 
alert(b); //Value is Volvo

var c = null;
alert(c); //Value is null

4
请为这句话添加一些解释,说明它的意思。 - Ry-
这并不真正检查 null - Sebastian Simon

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