JavaScript中的所有类型(Primitive和Object)

JavaScript Primitive

Primitive (primitive value, primitive data type) 原始类型,一共有7种

Primitive的定义:不是 object, 并且没有methods和properties (没有方法,没有属性)

  • string
  • number
  • bigint
  • boolean
  • undefined
  • symbol
  • null

Primitive都为immutable,不能更改(只能给变量重新赋值,指将另一个primitive value赋值给一个variable,在这个过程中primitive value本身仍然是不可变的)

除了nullundefined外,所有primitive type都有它们各自的object wrapper type

除了null外,所有primitive type都可以使用typeof操作符来判断类型 (但typeof null会返回'object'

原始类型 Primitive Typetypeof 操作符的返回值Object wrapper 类型
Null"object"没有
Undefined"undefined"没有
Boolean"boolean"Boolean
Number"number"Number
BigInt"bigint"BigInt
String"string"String
Symbol"symbol"Symbol

Primitive没有methods,但如果访问一个primitive的property或methods,JavaScript会自动wrap进一个它的object wrapper里,并调用object的方法。

例如:

1
"foo".includes("f")  // returns true

JavaScript自动做的事情是

1
(new String("foo")).includes("f")  // String.prototype.includes()

JavaScript’s 7 Primitive Types + 1 Object Type

  • Null 类型: 只有一个值: null

  • Undefined 类型: 只有一个值 undefined.

    • 语义上 undefined 通常表示值的缺失,null表示object的缺失,可以算作typeof null === 'object'的借口
      • 实际上 typeof null === 'object' 是历史原因,是设计缺陷。参考: mdn web docs
    • 一些场合下,JavaScript会自动赋值undefined: 函数传参没传、object的属性找不到(例如 obj.dontexist)、函数不给返回值直接return;、声明变量不初始化(例如let x;)、许多方法未找到值 (例如Array.prototype.find())
  • Number 类型:双精度64bit的IEEE754浮点数

    • 忘了IEEE754的话回去看ShanghaiTech CS110:链接 --> Lecture 7
    • 能够表示的正数浮点数范围为 Number.MIN_VALUENumber.MAX_VALUE (约为5e-324 到 1.79e308)
    • 能够精确表示的整数范围为 Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER ( (2531)-(2^{53}-1)25312^{53}-1 )
    • 大于Number.MAX_VALUE或小于 -Number.MIN_VALUE 的数会被转换为 Number.POSITIVE_INFINITYNumber.NEGATIVE_INFINITY
    • 小于Number.MIN_VALUE的正数,或大于 -Number.MIN_VALUE的负数,会被转换为 0-0
  • BigInt 类型

    • 可以表示任意大小的正数Integer,大于 Number.MAX_SAFE_INTEGER 也可以

    • 用数字+后缀 n表示,或使用 BigInt(数字)表示(不要使用new 操作符), 例如

      1
      2
      const a = 9007199254740991n;
      const b = BigInt(9007199254740991);
    • 支持大部分操作符:+, -, *, /, %, **, >>, <<, &, |, ^, ~, -, ++, --。但是通常这些操作符要求左右两边类型相同,要么都是BigInt,要么都是Number或其它

  • String 类型

    • UTF-16编码的字符串,是一个16-bit unsigned integer值组成的sequence
  • Symbol 类型

    • 这个是ES6新增的原始类型
    • 是唯一不可变的primitive类型.
  • Object 类型

    • 除原始类型外,所有 JavaScript 值均为Object对象

      • 普通对象、数组、函数、Date, RegExp, Map, Set 等都是对象
    • 对象是键值对的组合,这里的“键”通常为 string 字符串,也可以是 Symbol

    • 关于 Object 的 data property和 accessor property 可参考另一篇post: 49_js_accessor_property

    • typeof object 返回值均为 'object', 但有一个例外,typeof function 返回值为 'function'

Type coercion 奇奇怪怪的类型转换

JavaScript为弱类型语言,隐式类型转换过于复杂,且容易出错,不建议使用。

建议别学这些,建议使用TypeScript或Jsdoc规范类型

  • 首先,使用 == 比较两个object,只比较的是它们是否指向同一个对象,否则一律为 false. 有点类似于Python3中的 is 操作符

  • object不会被coerce,只有primitive types能被coerce

    • 如果需要对object进行 coerce, 则需要先将这个object转为primitive type(例如转string),然后如果仍需coerce,则再对primitive type做coerce操作
  • object转为primitive type的过程如下,依次进行

    • (ES6新增) 先调用 obj[Symbol.toPrimitive]() 方法,如果返回值为primitive则结束,否则继续下面的尝试
    • 先调用 obj.valueOf(), 如果返回值为primitive则结束,否则继续
    • 再调用 obj.toString(), 如果返回值为primitive则结束,否则继续
    • 仍然不行则 throw TypeError
  • 对于大部分object,toString() 方法会返回 [object ObjectName], 但是有一些例外,例如

    • 函数function的toString() 会返回函数体代码本身,如果函数为内置函数则返回 function funcName(){[native code]} 例如

      1
      2
      3
      4
      function foo(x) { return x * 2; }
      console.log(foo.toString()); // "function foo(x) { return x * 2; }"

      console.log(Math.max.toString()); // "function max() { [native code] }"
    • 数组Array的toString() 会返回其所有值使用逗号,join起来的结果,例如

      1
      console.log([1, {}, 3].toString());  // "1,[object Object],3"
    • Date对象的 toString() 返回值为locale time,例如

      1
      2
      console.log(new Date('2011-04-05T14:19:19Z').toString());
      // Tue Apr 05 2011 10:19:19 GMT-0400 (Eastern Daylight Time)"
    • Error对象

      1
      console.log(new Error('Oops!').toString());  // "Error: Oops!"
    • Symbol类型

      1
      2
      const sym = Symbol('id');
      console.log(sym.toString()); // "Symbol(id)"
    • 除此之外,大部分object仍然继承自 Object.prototype.toString, 输出格式为 '[object Type]'

      1
      2
      console.log(({}).toString());         // "[object Object]"
      console.log((new Map()).toString()); // "[object Map]"
  • 转为primitive之后,需要考虑的事情就变成了primitive如何互相比较或操作

  • 加号 + operator:

    • 如果表达式为 +value, 则永远会将value给coerce成一个 number 类型
    • 如果表达式为 anything + string, 则永远会把 anything 给coerce成string类型,再拼接字符串
    • 除此之外,为数字相加
  • 如果表达式需要布尔值 (例如 if(value), !value, !!value),则会coerce成 boolean 类型

    • Coerce成 boolean 的规则: null, undefined, 0, -0, ''空字符串, false, 转换成布尔会变成 false, 其余所有东西转换成布尔都是 true
  • 其它coerce primitive values的规则

    • number转string: 数值的字符串表达式,可能会使用科学技术法表示。参考 Number.toString()
    • string转number: 如果string表达的是有效数字(包括科学技术法、16/8/2进制等),则转换为对应的number,否则转为 NaN
    • boolean转number: true 转为 1, false 转为 0
    • null 和 undefined 转 number 分别为 0, NaN (注意 null0 不是 NaN !!!)
    • null 和 undefined 转 string 分别为 'null', 'undefined'
  • 类型转换的例子

    • Code:

      1
      console.log(undefined + [])  // 'undefined'

      加号左边undefined 是原始类型,[]空数组是一个object。所以需要先将空数组 [] 转为原始类型。按照固定的依次顺序进行转换:

      [][Symbol.toPrimitive]undefined 无法调用

      [].valueOf() 返回值为空数组 [] 本身,仍是object,不是primitive类型

      [].toString() 返回值为空字符串 '', 空字符串是 string 类型,是基本类型,完成

      现在要将 undefined 和空字符串 '' 相加,任何值跟string相加都要先转为 string, 而基本类型 undefined 转为string的值即为字符串 'undefined'

      因此 undefined + [] 即为 'undefined' + '', 字符串拼接结果为 'undefined'

    • Code

      1
      console.log([] + {})  // '[object Object]'

      加号左右两边的 []{} 都是object,都需要转换成原始类型

      上面的例子说过空数组 [] 转原始类型为字符串 ''。而 {} 转原始类型过程如下

      ({})[Symbol.toPrimitive]undefined 无法调用

      ({}).valueOf() 返回值为对象 {} 本身,仍是object,不是primitive类型

      ({}).toString() 返回值为字符串 '[object Object]'

      将字符串 ''与字符串 '[object Object]' 相拼接,结果为字符串 '[object Object]'


JavaScript中的所有类型(Primitive和Object)
https://www.billhu.us/2025/061_javascript_types/
Author
Bill Hu
Posted on
July 26, 2025
Licensed under