undefined 与 null 详解

目录

  1. null 与 undefined 的区别
  2. null 使用场景
  3. typeof null 历史遗留问题
  4. 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表示 布尔类型

在这里插入图片描述

版本迭代前的 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' 但是最终被拒绝, 因为代码的历史缘由不想得罪更多人

总结

  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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值