下班前几分钟,我彻底弄懂了 undefined 和 null 的区别
目录
前言
一、基本概念
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 的区别相关推荐
- 三分钟带你弄懂slot插槽——vue进阶
文章目录 三分钟带你弄懂slot插槽--vue进阶 一.概述 程序员之死 什么是 slot插槽? 2.6.0 版本中的 slot 二.具名插槽 例子 效果图 代码 三.小惊喜 三分钟带你弄懂slot插 ...
- hwt字体转换ttf_五分钟教你弄懂了字体反爬是个啥
今天的文章内容主要是关于字体反爬. 目前已知的几个字体反爬的网站是猫眼,汽车之家,天眼查,起点中文网等等. 以前也看过这方面的文章,今天跟个老哥在交流的时候,终于实操了一把,弄懂了字体反爬是个啥玩意. ...
- 下班前几分钟,我学会了如何使用 Vuex
目录 前言 正文 一.基本概念 二.项目场景 三.如何使用 1.安装 2.State 初始值 3.Getters 修饰值 4.Mutations 修改值 5.Actions 异步修改值 四.总结 五. ...
- 下班前几分钟,我彻底弄懂了并查集
目录 一.并查集的由来 二.代表元法 2.1 初始化 2.2 查询 2.3 合并 2.4 设计理念 三.并查集的应用 3.1 合并集合 3.2 连通块中点的数量 3.3 亲戚 3.4 省份数量 Ref ...
- 花了10分钟,终于弄懂了特征值和特征向量到底有什么意义
转自 http://k.sina.com.cn/article_6367168142_17b83468e001005yrv.html 有振动 就有特征值 今天,超模君看到了一句神翻译: 吓得超模君马上 ...
- 下班前几分钟,逮到一个腾讯10年老测试开发,聊过之后彻底悟了...
优秀的人真的是比比皆是,不比不知道,一比吓一跳 老话说的好,这人呐,一单在某个领域鲜有敌手了,就会闲得蛋疼.就在昨天下班的前几分钟认识了一个在阿里工作了 10 年的测试开发,因为本人天赋比较高,平时工 ...
- 下班前10分钟光速安装skywalking并解决报错
看标题就知道我当时慌的一批 下载方式 可以从官网下载apache-skywalking-apm-$version.tar.gz包.在windows或linux下都可以解压,因为运行参数需要指定里面的j ...
- 三分钟带你弄懂GFS(Google File System)
提示:预计阅读时间三分钟,该文章仅对GFS做了一的简略介绍,细节方面建议阅读原文. 文章目录 前言 一.GFS是什么? 1.1 简单介绍 1.2 我们为什么需要阅读GFS的论文? 1.3 GFS论文对 ...
- 趁着下班前五分钟书写——Vue3通讯(常规写法、语法糖、v-modle、兄弟通讯)
回顾 前期 [科技与狠活]-- JS实现页面阻塞三秒_0.活在风浪里的博客-CSDN博客_js实现阻塞while 循环 及 do while 的使用, 利用循环实现伪暂停进程 n 秒https: ...
最新文章
- [kuangbin带你飞]专题六 最小生成树 L - 还是畅通工程 (简单最小生成树)
- 【Network Security!】关于DDOS攻击的现状分析与探索
- 将Excel文件转换为Html
- VTK:PolyData之CellLocator
- html显示和隐藏不占空间的是什么,css怎么设置不占用空间的隐藏?
- (大数据工程师学习路径)第五步 MySQL参考手册中文版----MySQL视图
- ubuntu16.04下安装windows软件,以及卸载.
- 中小卖家需要避开的三个坑
- java socket 握手_TCP建立连接三次握手过程详解(wireshark截图、java socket源码)
- Linux 命令(79)—— pidof 命令
- 工厂流水线数据采集方案
- 如何设置和修改网页地址栏图标favicon.ico?
- 任务栏管理器无法结束任务 taskkill也无法结束任务 pchunter加载驱动失败
- 射线法判断点在多边形内适用范围_重庆球墨铸铁X射线实时成像实时成像系统真诚合作_丹东华日电气...
- 如何在cad中模块计算机,AutoCAD如何创建块 CAD模块创建方式一览
- 二阶无源低通滤波器幅频特性曲线_低通无源滤波器设计-详细
- 一个程序员的诗集【古诗篇】
- 结合P2P软件使用Ansible分发大文件
- SQL数据库移植到ARM板步骤
- div内li标签间距_css怎样让li间距增大?