我想知道JavaScript中null和undefined之间的区别。


当前回答

已经给出了很多“技术性”的答案,从JS仅仅是一种编程语言的有限角度来看,所有答案都是正确的。

然而,我想补充以下想法,特别是当您将TypeScript代码作为更大项目/(企业)应用程序的一部分时:

当与某种后端交谈时,您很可能会收到JSON虽然一些后端正确地避免了在JSON中使用“null”(删除那些财产),但其他后端没有这样做现在,虽然“null”可能意味着该值是故意缺失的,但更多情况下,它并没有传达这一含义。大多数数据库使用“null”只是因为它们没有“undefined”类型。但真正的含义只是“未定义”。因此,您永远无法知道“null”值是否真的意味着故意缺席。因此,“空”并不意味着故意选择“缺失值”。一般来说,这是无法决定的。因此,在语义上,“null”和“undefined”实际上是完全相同的。

因此,为了协调一致,我坚决反对使用“null”,并希望鼓励您停止在代码中使用“null“。这比你想象的要容易得多。别误会我。我不是说不处理“null”值,只是为了避免在代码中显式使用它们。换句话说:您的代码应该仍然能够处理来自应用程序外部的意外传递的“null”值,例如通过第三方库(如Angular)或第三方后端。

以下是实现这一目标的指导原则:

避免直接的未定义类型保护(例如,如果(值==未定义){…}。相反,使用间接类型保护(也称为真实性检查),例如if(value){…}每当0或空字符串有意义时,请使用像Lodash的isNil这样的显式助手方法或在比较中包含有意义的值(例如,如果(!value&&value!==0){…})考虑使用不允许使用null的lint规则

其他回答

null和undefined都用于表示缺少某个值。

var a = null;

a被初始化和定义。

typeof(a)
//object

null是JavaScript中的对象

Object.prototype.toString.call(a) // [object Object]

var b;

b未定义且未初始化

未定义的对象财产也是未定义的。例如,“x”未在对象c上定义,如果您尝试访问c.x,它将返回undefined。

通常,我们为未定义的变量赋值null。

undefined表示变量已声明但尚未赋值:

var测试var;console.log(testVar)//显示未定义console.log(testVar类型)//显示未定义

null是赋值。它可以作为无值表示分配给变量:

var testVar=空;console.log(testVar)//显示nullconsole.log(testVar类型)//显示对象

从前面的示例中可以清楚地看到,undefined和null是两种不同的类型:undefineed是类型本身(undefine),而null是对象。

证明:

console.log(null==未定义)//false(类型不同)console.log(null==undefined)//true(但为“相同值”)console.log(null==null)//true(类型和值相同)

and

null = 'value' // Uncaught SyntaxError: invalid assignment left-hand side
undefined = 'value' // 'value'

引自Marijn Haverbeke第三版《Elquent Javascript》:

undefined和null之间的含义差异是Javascript设计的一个意外,大多数时候这并不重要。如果你真的需要关注这些价值观,我建议你将它们视为可以互换的

老实说,一开始,我对这个建议有点怀疑。然而,在我自己的解释中,这是一种懒惰(或渴望)的方式来处理他们的分歧。也许,我们根本不需要处理这些差异。如果我们必须这样做,我们可以延迟我们的担忧(直到我们不得不这样做),而不是在这些值(null和undefined)流经我们的代码的每一步都过度/防御性地担心它。

PS:这不是对你问题的直接回答。这只是一个相关的观点。

请仔细阅读以下内容。它应该可以消除您对JavaScript中null和undefined之间区别的所有疑虑。此外,您可以在答案末尾使用效用函数来获取更具体的变量类型。

在JavaScript中,我们可以有以下类型的变量:

未声明的变量已声明但未分配的变量未定义文字赋值的变量赋值为文本null的变量变量分配了除未定义或null以外的任何值

以下逐一解释了每种情况:

未声明的变量只能使用返回字符串“undefined”的typeof运算符进行检查不能用松散相等运算符(==undefined)检查,更不用说严格相等运算符(===undefineed),以及if语句和三元运算符(?:)-这些抛出引用错误已声明但未分配的变量typeof返回字符串“undefined”==检查null返回true==未定义的检查返回true==检查null返回false==未定义的检查返回trueif语句和三元运算符(?:)是否错误未定义文字赋值的变量这些变量与已声明但未分配的变量完全相同。赋值为文本null的变量typeof返回字符串“object”==检查null返回true==未定义的检查返回true==检查null返回true==检查未定义返回falseif语句和三元运算符(?:)是否错误变量分配了除未定义或null以外的任何值typeof返回以下字符串之一:“bigint”、“boolean”、“function”、“number”、“object”、“string”、“symbol”

以下提供了正确检查变量类型的算法:

获取变量的类型,如果它不是“object”,则返回它检查null,因为typeof null也返回“object”使用switch语句对Object.protype.toString.call(o)求值,以返回更精确的值。Object的toString方法为本机/主机对象返回类似“[Object ConstructorName]”的字符串。对于所有其他对象(用户定义的对象),它始终返回“[object object]”如果最后一部分是这种情况(变量的字符串化版本为“[objectObject]”),并且参数returnConstructorBoolean为真,则它将尝试通过对其进行字符串化并从中提取名称来获取构造函数的名称。如果无法访问构造函数,将照常返回“object”。如果字符串不包含其名称,则返回“匿名”

(支持ECMAScript 2020之前的所有类型)

function TypeOf(o, returnConstructorBoolean) {
  const type = typeof o

  if (type !== 'object') return type
  if (o === null)        return 'null'

  const toString = Object.prototype.toString.call(o)

  switch (toString) {
    // Value types: 6
    case '[object BigInt]':            return 'bigint'
    case '[object Boolean]':           return 'boolean'
    case '[object Date]':              return 'date'
    case '[object Number]':            return 'number'
    case '[object String]':            return 'string'
    case '[object Symbol]':            return 'symbol'

    // Error types: 7
    case '[object Error]':             return 'error'
    case '[object EvalError]':         return 'evalerror'
    case '[object RangeError]':        return 'rangeerror'
    case '[object ReferenceError]':    return 'referenceerror'
    case '[object SyntaxError]':       return 'syntaxerror'
    case '[object TypeError]':         return 'typeerror'
    case '[object URIError]':          return 'urierror'

    // Indexed Collection and Helper types: 13
    case '[object Array]':             return 'array'
    case '[object Int8Array]':         return 'int8array'
    case '[object Uint8Array]':        return 'uint8array'
    case '[object Uint8ClampedArray]': return 'uint8clampedarray'
    case '[object Int16Array]':        return 'int16array'
    case '[object Uint16Array]':       return 'uint16array'
    case '[object Int32Array]':        return 'int32array'
    case '[object Uint32Array]':       return 'uint32array'
    case '[object Float32Array]':      return 'float32array'
    case '[object Float64Array]':      return 'float64array'
    case '[object ArrayBuffer]':       return 'arraybuffer'
    case '[object SharedArrayBuffer]': return 'sharedarraybuffer'
    case '[object DataView]':          return 'dataview'

    // Keyed Collection types: 2
    case '[object Map]':               return 'map'
    case '[object WeakMap]':           return 'weakmap'

    // Set types: 2
    case '[object Set]':               return 'set'
    case '[object WeakSet]':           return 'weakset'

    // Operation types: 3
    case '[object RegExp]':            return 'regexp'
    case '[object Proxy]':             return 'proxy'
    case '[object Promise]':           return 'promise'

    // Plain objects
    case '[object Object]':
      if (!returnConstructorBoolean)
        return type

      const _prototype = Object.getPrototypeOf(o)
      if (!_prototype)              
        return type

      const _constructor = _prototype.constructor
      if (!_constructor)            
        return type

      const matches = Function.prototype.toString.call(_constructor).match(/^function\s*([^\s(]+)/)
        return matches ? matches[1] : 'anonymous'

    default: return toString.split(' ')[1].slice(0, -1)
  }
}

null是一个特殊值,表示“无值”。null是一个特殊的对象,因为typeof null返回“object”。

另一方面,undefined表示变量尚未声明,或未给定值。