基础到家得知识你真的了解吗?-JS数据类型和typeof

20 阅读3分钟

来一个基础他妈给基础开门-基础到家的知识-js的数据类型,没有任何其他答案了,这里的答案是唯一的,请往下看

序号原始类型(基本类型)typeof
1Numbernumber
2Booleanboolean
3Stringstring
4BigInt(ES11+)bigint
5Symbol(ES6+)symbol
6Undefinedundefined
7Nullobject
序号对象类型(复杂类型)typeof
8Objectobject/function

有同学可能会说,不对啊 数组,函数呢??

简单说:数组只是作为 Object 的特殊变体,并不是独立的基本类型,注意,这是官方严格定义的,只有这8种。

typeof结果对应问题

如上面表里展示的,这是js里面比较烦人的地方,为什么呢?他不对应。 虽然说大部分都是对应的,但是涉及到 null,和 object 时问题就来了。

一. typeof null === 'object'

如果有人问你为什么会这样呢?你可以明确告诉他:“这是js作者留下的坑”,没错,这是js作者亲自承认的设计缺陷。

核心原因:JavaScript 32 位存储的类型标记位冲突

JavaScript 最初在实现时,采用 32 位二进制值 来存储所有数据类型,这个 32 位值分为两部分:

  1. 前 3 位(类型标记位) :用于标识数据的基础类型;
  2. 后 29 位:用于存储数据的实际值或内存地址。

当时规定了各类数据类型的标记位:

  • 000:标记为 对象(object) ,后 29 位存储对象在内存中的地址;
  • 001:标记为字符串;
  • 010:标记为数字;
  • 100:标记为布尔值;
  • 110:标记为 undefined;

而 null 被设计为 表示 “空指针” (对应 C 语言中的 NULL 指针),在底层存储时,null 的 32 位二进制值被全部设为 000000...000。此时:

  • 它的前 3 位标记位是 000,恰好与 对象(object)  的类型标记位完全一致;
  • 当 typeof 运算符检测 null 时,会根据前 3 位标记位判断类型,最终返回 object,这就是该问题的本质。
  • 为什么不修复? 因为为了保证向后兼容,避免破坏现有代码生态,只能维持现有设计了;

二. typeof Object === 'object/function'

这里的Object表示的 对象类型 也有说是 引用类型 或者 复杂类型。包含数组(Array)、函数(Function)、日期(Date)、正则(RegExp)等子类型。

知识点来了,typeof 函数 结果是 function ,这个我们都知道函数也是对象的一种。那 函数对象普通对象 的区别呢?

{
 [[call]]
 [[construct]]
}

如上图所示,函数对象里包含两个内部方法一个是 [[call]] 一个是 [[construct]]

JavaScript 中,对象是否为 “函数对象” 的核心标识是:该对象是否拥有内置的 [[Call]] 内部方法(这是一个不可直接访问的内部属性,仅引擎可识别)

  • [[Construct]] 的核心作用:支持对象被 new 运算符调用,用于创建并返回新实例对象;
  • 存在性:普通函数 / 类 / 内置构造函数拥有 [[Construct]],箭头函数 / 内置工具函数无此方法;
  • [[Call]] 方法的作用:允许对象被作为函数调用(即通过 () 运算符执行,如 fn());
  • 只有函数对象(包括普通函数、箭头函数、构造函数、类等)才会拥有 [[Call]] 内部方法;
  • 普通对象({})、数组([])、日期(new Date())等均无 [[Call]] 方法。

typeof 运算符在检测时,会内部判断目标对象是否存在 [[Call]] 方法:

  • 若存在(函数对象):直接返回 function

总结

其实就是我觉的好像没啥要总结的。。。。。。