undefined 与 null 详解undefined 与 null 是两个常见且容易混淆的概念。虽然它们在某些情况下
目录
- null 与 undefined 的区别
- null 使用场景
- typeof null 历史遗留问题
- 推荐观看
- Reference
null 与 undefined 区别
null 与 undefined 大致的意义是相同的, 但它们的类型和具体用途有明显区别
- 类型不同
- null 为 object 类型
- undefined 为 未定义类型(undefined)
- 所指代意义不同(null 有意赋值, undefined 由系统进行分配)
- null 表示空值, 一般有意
- undefined 表示 值未定义, 由系统进行分配
// 宽松相等 成立 是因为他们的表示的意思是相同的
console.log(null == undefined); // true
// 严格相等 不成立 是因为 他们的类型是不同的
console.log(null === undefined); // false
console.log(typeof null); // object
console.log(typeof undefined); // undefined
什么情况会出现 null 1. DOM 元素未获取到 2. 使用 null 对未来需要赋值的引用值 占位
// 情况1
const el = document.getElementById('app'); // 当没有 id 为 app 元素时 为 null
// 情况2
// 先用 null 占位 表示未来需要赋值 引用类型
let arr = null;
// more code...
arr = [1, 2, 3, 4]; // 后续需要赋值引用类型
什么情况会出现 undefined
- 当变量未定义值时
- 当使用未定义的变量时
- 当函数没有返回值时
- 当函数返回
void
时(可能会用到的) - 当访问越过数组边界访问时(最常会碰到的)
- 当访问不存在的属性时(最常会碰到的)
// 情况1
var a;
console.log(a); // undefined
// 情况2
console.log(typeof b); // undefined
// 情况3
function test() {}
console.log(test()); // undefined
// 情况4
function test1() {
return void 0;
}
// 情况5
console.log(test1()); // undefined
// 情况6
const arr = [0, 1];
console.log(arr[2]); // undefined
// 情况7
const obj = {
a: 1
};
console.log(obj.b); // undefined
null 的使用场景
日常开发通常使用 null 来进行提前占位的
// DOM 元素频繁操作
(function() {
const nodeAll = document.querySelectorAll('div');
function changeNodeColor() {
let node = null;
for (let i = 0; i < nodeAll.length; i++) {
node = nodeAll[i]; // 存储起来 避免频繁使用访问
node.style.color = '#F00';
node.style.background = '#F00';
}
}
})();
// 获取数据以便后续使用
(function() {
let data = null;
fetch('https://YOUR_IP_ADDRESS').then(res => {
data = res.json();
}).then(res => {
console.log(data);
});
})();
(function() {
let userInfo = null;
// more code
userInfo = {
user: 'Xiao',
};
})();
typeof null 历史遗留问题
typeof null === 'object'
原因是 JS 引擎底层是使用 前三位二进制位作为 判断依据, 而 null 在绝大多数 系统/平台 中表示 全0所以 null 就被断定为 object 类型, 这是一个历史遗留问题而非设计问题
bit | description |
---|---|
000 | 表示 对象引用 |
1 | 表示 31 bit有符号整形 |
010 | 表示 双精度浮点型 |
100 | 表示 字符串 |
110 | 表示 布尔类型 |
版本迭代前的 JS_TypeOfValue 源码
截至当前 JS_TypeOfValue 方法被重写为如下 该源码所在位置: JSAPI
JS_PUBLIC_API JSType JS_TypeOfValue(JSContext* cx, HandleValue value) {
AssertHeapIsIdle();
CHECK_THREAD(cx);
cx->check(value);
// 对 value 进行类型判断
return TypeOfValue(value);
}
TypeOfValue方法判断顺序: 浮点,数字均为整形, null 直接返回 object, string/boolean/undefined/object/bigint/symbol 返回自身
JSType js::TypeOfValue(const Value& v) {
switch (v.type()) {
case ValueType::Double: // 判断浮点与整数
case ValueType::Int32:
return JSTYPE_NUMBER;
case ValueType::String: // 判断浮点与整数
return JSTYPE_STRING;
case ValueType::Null: // 是否为 null
return JSTYPE_OBJECT;
case ValueType::Undefined: // 是否为 undefined
return JSTYPE_UNDEFINED;
case ValueType::Object: // 是否为引用类型
return TypeOfObject(&v.toObject());
#ifdef ENABLE_RECORD_TUPLE
case ValueType::ExtendedPrimitive:
return TypeOfExtendedPrimitive(&v.toExtendedPrimitive());
#endif
case ValueType::Boolean: // 是否为 布尔
return JSTYPE_BOOLEAN;
case ValueType::BigInt: // 是否为 bigint
return JSTYPE_BIGINT;
case ValueType::Symbol: // 是否为 symbol
return JSTYPE_SYMBOL;
case ValueType::Magic:
case ValueType::PrivateGCThing:
break;
}

ReportBadValueTypeAndCrash(v);
}
在 ECMA6 中就有提案说要修改为 typeof null === 'null'
但是最终被拒绝, 因为代码的历史缘由不想得罪更多人
总结
- undefined 表示未定义值, null 表示值为空
- undefined 一般由系统分配, 只有函数中返回 void 是较为常用的
- null 有意分配对赋引用值之前的提前占位
- 在底层已经对 原来的
JS_TypeOfValue
方法进行更改, 其核心逻辑在于TypeOfValue
方法, 该方法不同与之前的方法是没有对 null 进行处理的
推荐观看(暂时未编写完毕, 后续填坑)
- 判断类型的四种方式(你可以准确判定出 null 类型)
Reference
转载自:https://juejin.cn/post/7418942407917469707