一 种类 - 目前8种

JavaScript默认有6种类型:

  • null
  • undefined
  • number
  • string
  • boolean
  • object

ES6新增类型

  • symbol(使用内置Symbol函数创建)

ES10新增类型

  • bigint (在数字后缀加上n)

    二 类型判断 - typeof使用

    在JS中,可以使用 typeof 来进行辨别
    1. typeof undefined === 'undefined';
    2. typeof 23 === 'number';
    3. typeof "23" === 'string';
    4. typeof true === 'boolean';
    5. typeof {} === 'object';
    6. // ES6 新类型
    7. typeof Symbol() === 'symbol';
    8. // ES10 新类型
    9. typeof 999999999999999999999999n === 'bigint';
    当对function使用typeof时候,会返回类型 function
    1. typeof function a(){} === 'function';
    这样搞得好像function也是JavaScript的一种内置类型一样。
    可以实际function其实也是object类型下的一个子类型,只是其内置调用属性[[Call]]属性实现了调用。
    其实数组也是object下的一个子类型
    1. typeof [] === 'object';
    所以有的场景下会说:JavaScript内皆是对象。(虽然该说法有局限,但在日常开发中经常如此。)。

在typeof使用中还有个例外:null,如果使用 typeof 进行辨别,会出现很奇怪的结果

  1. typeof null === 'object';

这个bug由来已久,已经存在JavaScript中存在了二十多年,如果要判断对象是否是 null 可以使用如下判断

  1. var a = null;
  2. (!a && typeof a === "object")

null在typeof下为何为”object”

该问题可以追溯到 JavaScript第一个版本,单个值在栈中占用32位的储存单元。
而32位储存单元中分为:3个类型标签位,29个实际数据位。
这三个类型标签处于低位,即:第0~2位
故可以分为五种情况:
000 —> object
001 —> number
010 —> number(浮点数)
100 —> string
110 —> boolean
而undefined为 -230 在整数范围之外。
null是从第0位到第31位数都为0,所以正好和object的第0~3位数全为0的情况吻合
所以typeof会认为 null 是 object 类型,这算是一个bug吧,目前看来 JavaScript团队还没有修复的打算。

三 值和类型

在JavaScript中,变量是没有类型的,只有值才有,且变量所持有的值可以随时变化为任何类型。
所以JavaScript也被称为“弱语言”
个人感觉这也是为什么JavaScript是一门非常容易上手的语言,新手甚至都不需要花专门时间看专业书籍,仅需看看前人的代码就可以开始愉快的开发之旅!
(但从后期大型工程开发来看,这种模式也有很严重的弊端。所以出现了像TypeScript这种JS超集的”加强包”来强化JS。但综合来看,JavaScript是一门很优秀且对新手很友好的语言。)

神奇的undefined

在大多数开发者心里undefined其实等同于undeclared(为声明)。
这也不能怪开发者,毕竟在typeof下它也是这么认为的

  1. // 声明但为赋值
  2. var a;
  3. typeof a; // 'undefined'
  4. typeof b; // 'undefined'
  5. b; // ReferenceError: b is not defined

这就让人很抓狂了,且在对象中直接引用未声明的属性也是如此

  1. const a = {}
  2. a.b; // undefined

这就是为什么大多数开发者认为:undefined(声明未赋值) === undeclared(未声明)。
其实这算是JavaScript的一种安全防范机制,避免在开发过程中过多出现 ReferenceError 错误。
在大部分的开发场景下这样的处理方式也无伤大雅。
但注意!!!在 ES6 中要注意一种情况要格外小心

  1. const a = { one: 1 };
  2. const b = { one: undefined };
  3. const c = { };
  4. // 会覆盖
  5. { ...a, ...b }; // { one: undefined }
  6. // 不会覆盖
  7. { ...a, ...c }; // { one: 1 }

在使用 展开运算符 进行对象合并时候,undefined(声明未赋值)和undeclared(未声明)是有质的区别的!
只要后整对象的内部声明了,哪怕真的值是 undefined 也是会覆盖前面对象内的属性。这里要注意!