总的来说 null 和 undefined 都代表空,主要区别在于 undefined 表示尚未初始化的变量的值,而 null 表示该变量有意缺少对象指向。
值 null 是一个字面量,不像 undefined ,它不是全局对象的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。
undefined 是 全局对象 的一个属性。也就是说,它是全局作用域的一个变量。undefined 的最初值就是原始数据类型 undefined 。
接下来我们看一张比较经典的图片,该图来自 stackoverflow 的回答,本人没有找到准确的出处。
在更深入理解 null 和 undefined 的区别前,我们首先要知道 null 和 undefined 在 JS 中有什么不同的表现形式,用以方便我们更好的理解 null 和 undefined 的区别。
typeof null // 'object'
typeof undefined // 'undefined'
typeof null // '[object Null]'
typeof undefined // '[object Undefined]'
null == undefined // true
null === undefined // false
!!null === !!undefined // true
JavaScript 中第一个对象的原型指向 null 。
Object.getPrototypeOf(Object.prototype) // null
let a = undefined + 1 // NaN
let b = null + 1 // 1
Number(undefined) // NaN
Number(null) // 0
JSON.stringify({a: undefined}) // '{}'
JSON.stringify({b: null}) // '{b: null}'
JSON.stringify({a: undefined, b: null}) // '{b: null}'
function test(n) {
let undefined = 'test'
return n === undefined
}
test() // false
test(undefined) // false
test('test') // ture
let undefined = 'test' // Uncaught SyntaxError: Identifier 'undefined' has already been declared
typeof null 输出为 'object' 其实是一个底层的错误,但直到现阶段都无法被修复。
原因是,在 JavaScript 初始版本中,值以 32位 存储。前 3位 表示数据类型的标记,其余位则是值。
对于所有的对象,它的前 3位 都以 000 作为类型标记位。在 JavaScript 早期版本中, null 被认为是一个特殊的值,用来对应 C 中的 空指针 。但 JavaScript 中没有 C 中的指针,所以 null 意味着什么都没有或者 void 并以 全0(32个) 表示。
因此每当 JavaScript 读取 null 时,它前端的 3位 将它视为 对象类型 ,这也是为什么 typeof null 返回 'object' 的原因。
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
这是因为 各个类中重写了 toString 的方法,因此需要调用 Object 中的 toString 方法,必须使用 toString.call() 的方式调用。
对于 Object 对象,直接调用 toString() 就能返回 '[object Object]' 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
很多文章说:undefined 的布尔值是 false , null 的布尔值也是 false ,所以它们在比较时都转化为了 false ,所以 undefined == null 。
实际上并不是这样的。
ECMA 在 11.9.3 章节中明确告诉我们:
If x is null and y is undefined, return true.
If x is undefined and y is null, return true.
这是 JavaScript 底层的内容了,至于更深入的内容,如果有兴趣可以扒一扒 JavaScript 的源码。
这涉及到 JavaScript 中的隐式类型转换,在执行 加法运算 前,隐士类型转换会尝试将表达式中的变量转换为 number 类型。如:'1' + 1 会得到结果 11。
至于为什么执行如此的转换方式,我猜测是 JavaScript 早期的一个糟糕设计。
从语言学的角度来看:
null 意味着一个明确的没有指向的空值,而 undefined 则意味着一个未知的值。
在某种程度上, 0 意味着数字空值。
这虽然看起来有些牵强,但是我在这一阶段能所最能想到的可能了。
其实这条没有很好的解释方式, JSON 会将 undefined 对应的 key 删除,这是 JSON 自身的转换原则。
在 undefined 的情况下,有无该条数据是没有区别的,因为他们在表现形式上并无不同:
let obj1 = { a: undefined }
let obj2 = {}
console.log(obj1.a) // undefined
console.log(obj2.a) // undefined
但需要注意的是,你可能在调用接口时,需要对 JSON 格式的数据中的 undefied 进行特殊处理。
JavaScript 对于 undefined 的限制方式为全局创建了一个只读的 undefined ,但是并没有彻底禁止局部 undefined 变量的定义。
据说在 JavaScript 高版本禁止了该操作,但我没有准确的依据。
请在任何时候,都不要进行 undefined 变量的覆盖,就算是你的 JSON 转换将 undefined 转换为 '' 。也不要通过该操作进行,这将是及其危险的行为。
这是一条公说公有理婆说婆有理的争议内容。
本人更倾向于使用 null ,因为这是显示定义空值的方式。我并不能给出准确的理由。
但关于使用 undefined 我有一条建议:
如果你需要使用 undefined 定义空值,请不要采取以下两种方式:
进而采取下面这种方式显式声明 undefined :
终于将 undefined 和 null 的基本区别搞定了。
(冬季零下十度、夏季四十一二)养护环境窗边、阳台- 1 品种选择 -1 、强健易长大不易徒长 新手推荐品种:日轮玉、紫勋富贵玉、微纹玉、曲玉、荒玉(后两种种子较贵,建议有播种养护经验后再入手)日轮玉既有普通品种,又有绿光阳、绿流水、全窗等高端品种,强健生长快,颜值高,强力推荐曲玉也是大爱,初看不起眼
2024-11-15 10:47:31如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。例如,[2,3,4] 的中位数是 3[2,3] 的中位数是 (2 + 3) / 2 = 2.5设计一个支持以下两种
2024-11-15 10:36:11满族的印记之“长白山” 这两次吉林省内自驾游,分别是2016年6月9日的端午节小长假,和2018年的“五一”小长假。2016年那次的路线是通化-长白山-珲春防川-松花湖,4天行程1300多公里;2018年那次是通化-珲春防川-敦化,3天行程1200多公里。这两次都有珲春防川,是因为这里有个“一眼望
2024-11-15 10:21:171963年《天龙八部》小说连载于明报,1982年它的第一部影视化作品播出,如今40年过去了《天龙八部》电视剧共有五版,但要数最经典的当属1997年黄日华版的。当时内地共有34家电视台同时段播放,大街小巷唱响的都是“笑你我枉花光心计,爱竞逐镜花那美丽......”,直接创下年度亚洲收视率第一的佳绩。如
2024-11-15 10:06:24中国象棋(一)两军对垒阵势严,红先黑后规不变。士相左右严防护,将帅居中号令传。車占先机任纵横,马踏斜日忙参战。炮想打杀隔一子,兵卒纷纷只向前。步步紧逼须较智,不知谁奏凯歌还。(二)楚汉两相争,红黑竞英雄。问谁领风骚,全凭智谋定。(三)楚河汉界起纷争,红先黑后竞输赢。步步惊心谋后动,巧显智力也愉情。(
2024-11-15 09:51:26(冬季零下十度、夏季四十一二)养护环境窗边、阳台- 1 品种选择 -1 、强健易长大不易徒长 新手推荐品种:日轮玉、紫勋富贵玉、微纹玉、曲玉、荒玉(后两种种子较贵,建议有播种养护经验后再入手)日轮玉既有普通品种,又有绿光阳、绿流水、全窗等高端品种,强健生长快,颜值高,强力推荐曲玉也是大爱,初看不起眼
◆中位数公式是怎么来的(算法:数据流中的中位数) ◆长白山天池没人下去吗(长白山现在还封山吗?) ◆天龙八部虚竹扮演者叫什么(黄日华版《天龙八部》演员现状) ◆象棋棋谱口诀顺口溜大全(中国象棋打油诗) ◆弹簧机器调机过程(弹簧机生产时弹簧外径如何调整?)