目录

前言

一、基本概念

1、undefined

2、null

二、简单区别

三、表现形式

1、typeof

2、== 与 ===

3、Object.prototype.toString.call

4、+ 运算 与 Number()

5、JSON.stringify

6、let undefiend = 'test'

四、建议


前言

undefined 和 null 的区别是个老生常谈的话题了,之前我对二者的区别只是简单理解,例如二者转成 Boolean 类型都是 false、使用 == 进行比较时为 true、使用 === 进行比较时为 false 等,却没有真正系统地总结二者的区别。

某天,下班前几分钟,我彻底弄懂了 undefined 和 null 的区别。

一、基本概念

1、undefined

undefined 是“全局对象”的一个属性。也就是说,它是全局作用域的一个变量(下面展开对 undefined 变量的赋值操作)。undefined 的最初值就是原始数据类型 undefined。

2、null

null 是一个字面量,不像 undefined,它不是“全局对象”的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,或许更好理解。在 API 中,null 常使用来表示返回类型应是一个对象,但没有关联某个具体对象的这么一个值。

二、简单区别

总的来说,null 和 undefined 都表示空,主要区别在于 undefined 表示尚未初始化的变量的值,而 null 表示该变量有意缺少对象指向。

  • undefined

    • 这个变量从根本上就没有定义。

    • 隐藏式 空值。

  • null

    • 这个值虽然定义了,但它并未指向任何内存中的对象。

    • 声明式 空值。

以下是一张经典的图片,帮助我们理解。

三、表现形式

undefined 和 null 在 JavaScript 中有什么不同的表现形式,理解这些表现形式,可以帮助我们更好地理解 undefined 和 null 的区别。

1、typeof

console.log(typeof undefined);   // 'undefined'
console.log(typeof null);   // 'object'

typeof null 为 object 是一个历史遗留问题,直到现阶段都无法被修复。

在 JavaScript 初始版本中,值以 32位 存储。前 3位 表示数据类型的标记,其余位则表示值。
对于所有对象类型,它的前 3位 都以 000 作为类型标记位。在 JavaScript 早期版本中,null 被认为是一个特殊的值,用来对应 C 中的空指针,但 JavaScript 中没有 C 中的指针概念,所以 null 意味着什么都没有或者 void 并以 全0(32位)表示。

因此每当 JavaScript 读取 null 时,它的前 3位 将它视为对象类型,这也是为什么 typeof null 返回 object 的原因。

2、== 与 ===

console.log(null == undefined);   // true
console.log(null === undefined);   // false
console.log(!!null === !!undefined);   // true

这一点相信大家都明白,== 比较的是值,而 === 比较的是值跟类型。undefined 和 null 的布尔值都为 false,因此在用 == 比较时,为 true;而 undefined 和 null 的类型不同,因此在用 === 比较时为 false。

3、Object.prototype.toString.call

console.log( Object.prototype.toString.call(undefined) );   // '[object Undefined]'
console.log( Object.prototype.toString.call(null) );   // '[object Null]'

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]]。这是一个内部属性,其格式为 [object Xxx],其中 Xxx 就是对象的类型。

那么既然在 JavaScript 中,万物皆对象,为什么 xxx.toString() 不能返回变量类型?

这是因为各个类中重写了 toString(),因此需要调用 Object 中的 toString(),且必须使用 toString.call() 的方式调用。对于 Object 对象,直接调用 toString() 就能返回 [object Object];而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

4、+ 运算 与 Number()

let a = undefined + 1;
let b = null + 1;
console.log(a);   // NaN
console.log(b);   // 1console.log(Number(undefined));   // NaN
console.log(Number(null));   // 0

这涉及到 JavaScript 中的隐式类型转换,在执行加法运算前,隐式类型转换会尝试将表达式中的变量转换为 number 类型。如:'1' + 1 会得到结果 11。

  • null 转化为 number 时,会转换成 0。

  • undefined 转换为 number 时,会转换为 NaN。

5、JSON.stringify

console.log( JSON.stringify({a: undefined}) );   // '{}'
console.log( JSON.stringify({b: null}) );   // '{b: null}'
console.log( JSON.stringify({a: undefined, b: null}) );   // '{b: null}'

JSON 会将 undefined 对应的 key 删除,这是因为 JSON 自身的转换原则。在 undefined 的情况下,有无该条数据是没有区别的,因为他们在表现形式上并无不同。

let obj1 = { a: undefined };
let obj2 = {};console.log(obj1.a);   // undefined
console.log(obj2.a);   // undefined

6、let undefiend = 'test'

function test(params) {let undefined = 'test';   // 该作用域内undefined为一个变量,赋值为testreturn params === undefined;
}test();   // false
test(undefined);   // false
test('test');   // turelet undefined = 'test';   // Uncaught SyntaxError: Identifier 'undefined' has already been declared

JavaScript 对于 undefined 的限制方式为全局创建了一个只读的 undefined,但是并没有彻底禁止局部 undefined 变量的定义。

请在任何时候,都不要对 undefined 变量进行覆盖,就算是你的 JSON 转换将 undefined 转换为 '' ,也不要通过该操作进行,这将是及其危险的行为。

四、建议

如果你需要使用 undefined 定义空值,请不要采取以下两种方式:

  • let a;

  • let a = undefined;

进而采取下面这种方式显式声明 undefined:

  • let a = void 0;

下班前几分钟,我彻底弄懂了 undefined 和 null 的区别相关推荐

  1. 三分钟带你弄懂slot插槽——vue进阶

    文章目录 三分钟带你弄懂slot插槽--vue进阶 一.概述 程序员之死 什么是 slot插槽? 2.6.0 版本中的 slot 二.具名插槽 例子 效果图 代码 三.小惊喜 三分钟带你弄懂slot插 ...

  2. hwt字体转换ttf_五分钟教你弄懂了字体反爬是个啥

    今天的文章内容主要是关于字体反爬. 目前已知的几个字体反爬的网站是猫眼,汽车之家,天眼查,起点中文网等等. 以前也看过这方面的文章,今天跟个老哥在交流的时候,终于实操了一把,弄懂了字体反爬是个啥玩意. ...

  3. 下班前几分钟,我学会了如何使用 Vuex

    目录 前言 正文 一.基本概念 二.项目场景 三.如何使用 1.安装 2.State 初始值 3.Getters 修饰值 4.Mutations 修改值 5.Actions 异步修改值 四.总结 五. ...

  4. 下班前几分钟,我彻底弄懂了并查集

    目录 一.并查集的由来 二.代表元法 2.1 初始化 2.2 查询 2.3 合并 2.4 设计理念 三.并查集的应用 3.1 合并集合 3.2 连通块中点的数量 3.3 亲戚 3.4 省份数量 Ref ...

  5. 花了10分钟,终于弄懂了特征值和特征向量到底有什么意义

    转自 http://k.sina.com.cn/article_6367168142_17b83468e001005yrv.html 有振动 就有特征值 今天,超模君看到了一句神翻译: 吓得超模君马上 ...

  6. 下班前几分钟,逮到一个腾讯10年老测试开发,聊过之后彻底悟了...

    优秀的人真的是比比皆是,不比不知道,一比吓一跳 老话说的好,这人呐,一单在某个领域鲜有敌手了,就会闲得蛋疼.就在昨天下班的前几分钟认识了一个在阿里工作了 10 年的测试开发,因为本人天赋比较高,平时工 ...

  7. 下班前10分钟光速安装skywalking并解决报错

    看标题就知道我当时慌的一批 下载方式 可以从官网下载apache-skywalking-apm-$version.tar.gz包.在windows或linux下都可以解压,因为运行参数需要指定里面的j ...

  8. 三分钟带你弄懂GFS(Google File System)

    提示:预计阅读时间三分钟,该文章仅对GFS做了一的简略介绍,细节方面建议阅读原文. 文章目录 前言 一.GFS是什么? 1.1 简单介绍 1.2 我们为什么需要阅读GFS的论文? 1.3 GFS论文对 ...

  9. 趁着下班前五分钟书写——Vue3通讯(常规写法、语法糖、v-modle、兄弟通讯)

    回顾  前期   [科技与狠活]-- JS实现页面阻塞三秒_0.活在风浪里的博客-CSDN博客_js实现阻塞while 循环 及 do while 的使用, 利用循环实现伪暂停进程 n 秒https: ...

最新文章

  1. [kuangbin带你飞]专题六 最小生成树 L - 还是畅通工程 (简单最小生成树)
  2. 【Network Security!】关于DDOS攻击的现状分析与探索
  3. 将Excel文件转换为Html
  4. VTK:PolyData之CellLocator
  5. html显示和隐藏不占空间的是什么,css怎么设置不占用空间的隐藏?
  6. (大数据工程师学习路径)第五步 MySQL参考手册中文版----MySQL视图
  7. ubuntu16.04下安装windows软件,以及卸载.
  8. 中小卖家需要避开的三个坑
  9. java socket 握手_TCP建立连接三次握手过程详解(wireshark截图、java socket源码)
  10. Linux 命令(79)—— pidof 命令
  11. 工厂流水线数据采集方案
  12. 如何设置和修改网页地址栏图标favicon.ico?
  13. 任务栏管理器无法结束任务 taskkill也无法结束任务 pchunter加载驱动失败
  14. 射线法判断点在多边形内适用范围_重庆球墨铸铁X射线实时成像实时成像系统真诚合作_丹东华日电气...
  15. 如何在cad中模块计算机,AutoCAD如何创建块 CAD模块创建方式一览
  16. 二阶无源低通滤波器幅频特性曲线_低通无源滤波器设计-详细
  17. 一个程序员的诗集【古诗篇】
  18. 结合P2P软件使用Ansible分发大文件
  19. SQL数据库移植到ARM板步骤
  20. div内li标签间距_css怎样让li间距增大?

热门文章

  1. 兄弟连——我心中英雄们
  2. 首页 » 实用工具 » FastCopy – 文件快速复制工具更新
  3. python sort怎么用_Python的sort用法以及原理
  4. Python小辣鸡的逆袭第六章之字典
  5. 如何在VS2010中连接MySQL和Access数据库
  6. MPLS vpn和IPSEC vpn
  7. 平面设计师经常去的网站——字体网站
  8. linux企业防火墙软件,掌握Linux防火墙经典应用 让企业网络更安全
  9. LWN: 6.0 合并周期,第二部分!
  10. 个人记账管理系统的设计与实现