likes
comments
collection
share

undefined 与 null 详解undefined 与 null 是两个常见且容易混淆的概念。虽然它们在某些情况下

作者站长头像
站长
· 阅读数 23

目录

  1. null 与 undefined 的区别
  2. null 使用场景
  3. typeof null 历史遗留问题
  4. 推荐观看
  5. Reference

null 与 undefined 区别

null 与 undefined 大致的意义是相同的, 但它们的类型和具体用途有明显区别

  1. 类型不同
    1. null 为 object 类型
    2. undefined 为 未定义类型(undefined)
  2. 所指代意义不同(null 有意赋值, undefined 由系统进行分配)
    1. null 表示空值, 一般有意
    2. 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

  1. 当变量未定义值时
  2. 当使用未定义的变量时
  3. 当函数没有返回值时
  4. 当函数返回 void 时(可能会到的)
  5. 当访问越过数组边界访问时(最常会到的)
  6. 当访问不存在的属性时(最常会到的)
// 情况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 类型, 这是一个历史遗留问题而非设计问题

bitdescription
000表示 对象引用
1表示 31 bit有符号整形
010表示 双精度浮点型
100表示 字符串
110表示 布尔类型

undefined 与 null 详解undefined 与 null 是两个常见且容易混淆的概念。虽然它们在某些情况下 版本迭代前的 JS_TypeOfValue 源码 undefined 与 null 详解undefined 与 null 是两个常见且容易混淆的概念。虽然它们在某些情况下 截至当前 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;
  }

![Pasted image 20240927135937.png](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/2a615c29d3aa4e4e968ad09de12df202~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgU3Vsaw==:q75.awebp?rk3s=f64ab15b&x-expires=1728027290&x-signature=rSgldvcdzHAd7t%2BgxhQ2kUvxSis%3D)
  ReportBadValueTypeAndCrash(v);
}

在 ECMA6 中就有提案说要修改为 typeof null === 'null' 但是最终被拒绝, 因为代码的历史缘由不想得罪更多人

总结

  1. undefined 表示未定义值, null 表示值为空
  2. undefined 一般由系统分配, 只有函数中返回 void 是较为常用的
  3. null 有意分配对赋引用值之前的提前占位
  4. 在底层已经对 原来的 JS_TypeOfValue 方法进行更改, 其核心逻辑在于 TypeOfValue 方法, 该方法不同与之前的方法是没有对 null 进行处理的

推荐观看(暂时未编写完毕, 后续填坑)

  1. 判断类型的四种方式(你可以准确判定出 null 类型)

Reference

  1. ECMAScript null value
  2. ECMAScript null type
  3. ECMAScript5.1 type 运算符
  4. typeof null 历史问题
  5. MDN typeof
  6. gecko-dev
转载自:https://juejin.cn/post/7418942407917469707
评论
请登录