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


当前回答

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'

其他回答

已经给出了很多“技术性”的答案,从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。

理解差异的最佳方法是首先理清JavaScript的内部工作原理,并理解以下两者之间的含义差异:

let supervisor = "None"
    // I have a supervisor named "None"

let supervisor = null
    // I do NOT have a supervisor. It is a FACT that I do not.

let supervisor = undefined
    // I may or may not have a supervisor. I either don't know
    // if I do or not, or I am choosing not to tell you. It is
    // irrelevant or none of your business.

这三种情况的含义不同,JavaScript用两个不同的值(null和undefined)来区分后两种情况。您可以自由地明确使用这些值来表达这些含义。

那么,由于这种哲学基础而产生的一些JavaScript特定问题是什么呢?

没有初始值设定项的已声明变量将获得未定义的值,因为您从未说过预期值是什么。出租监督员;断言(主管==未定义);从未设置过的对象的属性求值为undefined,因为没有人说过该属性。const dog={name:“Sparky”,年龄:2};断言(dog.bred==未定义);null和undefined彼此“相似”,因为Brendan Eich是这么说的。但它们显然彼此不相等。断言(null==未定义);断言(null!==未定义);谢天谢地,null和undefined有不同的类型。null属于null类型,undefined属于undefined类型。这在规范中,但你永远不会知道这一点,因为我不会在这里重复这种奇怪的类型。如果函数到达其主体的末尾而没有显式返回语句,则返回undefined,因为您不知道它返回了什么。

顺便说一句,JavaScript中还有其他形式的“虚无”(学习哲学很好……)

NaN公司使用从未声明的变量并接收ReferenceError在其时间死区中使用let或const定义的局部变量并接收ReferenceError稀疏数组中的空单元格。是的,虽然它们与undefined相比==,但它们甚至没有定义。$节点>常量a=[1,未定义,2]>常量b=[1,2]>一个[1,未定义,2]>b级[1,<1空项>,2]

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

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

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

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

tl;博士

使用null设置一个已知为Object的变量。

使用undefined设置类型混合的变量。


这是我对5个原语和Object类型的用法,这解释了未定义或空的«用例»之间的区别。

一串

如果您知道一个变量在整个生命周期中只是一个字符串,那么按照惯例,您可以将其初始化为“”:

("") ? true : false; // false
typeof ""; // "string";
("Hello World") ? true : false; // true
typeof "Hello World"; // "string"

数字

如果您知道一个变量在所有生命周期中都只是一个数字,那么按照惯例,您可以将其初始化为0(如果0在您的使用中是一个重要值,则为NaN):

(0) ? true : false; // false
typeof 0; // "number";
(16) ? true : false; // true
typeof 16; // "number"

or

(NaN) ? true : false; // false
typeof NaN; // "number";
(16) ? true : false; // true
typeof 16; // "number"

布尔型

如果您知道一个变量只是一个布尔值,而所有生命周期,按照惯例,您可以将其初始化为false:

(false) ? true : false; // false
typeof false; // "boolean";
(true) ? true : false; // true
typeof true; // "boolean"

对象

如果您知道一个变量在所有生命周期中都只是一个Object,那么按照惯例,您可以将其初始化为null:

(null) ? true : false; // false
typeof null; // "object";
({}) ? true : false; // true
typeof {}; // "object"

注意:关闭null的智能用法是Object的错误版本,因为Object始终为true,因为typeof null返回对象。这意味着typeof myVarObject返回Object和null类型的一致值。

All

如果您知道一个变量有一个混合类型(所有生命周期中的任何类型),按照惯例,您可以将其初始化为undefined。