为什么 JavaScript 中有一个“null”值?

在JavaScript中,有两个值基本上说“我不存在” - 和.undefinednull

程序员没有给任何东西赋值的属性将是,但为了让一个属性成为,必须显式地赋值给它。undefinednullnull

我曾经认为需要因为是一个原始值和一个对象。实际上,两者都是基元值 - 这意味着两者都不能从构造函数返回,因为两者都将被转换为空对象(必须抛出错误以在构造函数中声明失败)。nullundefinednulltypeof null'object'undefinednull

它们也在布尔上下文中都计算为。我能想到的唯一真正的区别是,一个在数字上下文中计算为,另一个计算为。falseNaN0

那么,为什么两者兼而有之,如果这只会让那些在试图找出是否已设置属性时错误地检查的程序员感到困惑呢?undefinednullnull

我想知道的是,是否有人有一个合理的例子,其中有必要使用无法用它来表达。nullundefined

因此,普遍的共识似乎是,这意味着“没有这样的财产”,而意味着“财产确实存在,但没有价值”。undefinednull

如果JavaScript实现实际上会强制实施这种行为,我可以接受这一点 - 但是一个完全有效的原始值,因此可以很容易地将其分配给现有属性以打破此契约。因此,如果要确保某个属性是否存在,则必须使用运算符或无论如何。所以再一次:和 的单独值的实际用途是什么?undefinedinhasOwnProperty()undefinednull

当我想取消设置不再使用但我不想使用的属性的值时,我实际上会使用。我应该改用吗?undefineddeletenull


答案 1

问题实际上不是“为什么JS中有一个空值” - 在大多数语言中都有某种空值,它通常被认为是非常有用的。

问题是,“为什么JS中存在未定义的值”。使用的主要场所:

  1. 当您声明但不分配给它时,保留未定义;var x;x
  2. 当你的函数得到的参数少于它声明的参数时;
  3. 当您访问不存在的对象属性时。

null对于(1)和(2)*来说肯定同样有效。(3)真的应该马上抛出一个异常,而事实它没有,而不是返回这个以后会失败的怪异,是调试难度的一大根源。undefined

*:你也可以争辩说(2)应该抛出一个异常,但你必须为默认/变量参数提供一个更好,更明确的机制。

然而,JavaScript最初没有例外,或者任何方法都可以询问对象是否有某个名称下的成员 - 唯一的方法是(有时仍然是)访问该成员并查看您得到的内容。鉴于这已经有了一个目的,并且您很可能希望为其设置一个成员,因此需要不同的带外值。因此,正如您所指出的,这是有问题的,这是我们永远无法摆脱的另一个伟大的JavaScript“功能”。nullundefined

当我想取消设置不再使用但我不想删除的属性的值时,我实际上使用未定义。我应该改用空值吗?

是的。当其他语言可能引发异常时,请保留为信号的特殊值。undefined

null通常更好,除了在某些IE DOM接口上,设置某些内容可能会给您带来错误。通常在这种情况下,设置为空字符串往往有效。null


答案 2

最好在这里描述,但总结一下:

未定义是缺少类型和值,null 是缺少值。

此外,如果你正在做简单的“==”比较,你是对的,它们是一样的。但是尝试===,它比较了类型和值,你会注意到差异。