JS中数据的表达可分为数据类型、类型转换、数据声明三块。
数据类型
数据类型分成基本数据类型 和复杂数据类型 ,复杂数据类型都包含在全局对象 (Global)中,Global 中有全局属性 和全局对象 ,全局对象分为函数对象 和非函数对象 ,函数对象分为构造函数对象 和非构造函数对象。

关于数据类型划分的说明:
- 判断是否是函数对象,就是看这个对象是否可以作为函数直接使用
- 判断是否是构造函数对象,就是看这个对象有没有prototype属性,即原型对象
- 构造函数与普通定义的函数本质上一样,只是习惯上首字母大写
- JS中只有 通过函数声明 或class声明创建的函数才是构造函数
- 非构造函数可以通过new关键字、函数表达式或箭头函数表达式来创建,成员函数一般都是通过这几种方式创建 的,所以一般成员函数都是非构造函数
- 通过函数表达式创建的函数虽然是非构造函数,但是,当使用new关键字调用时,JS会自动创建一个新的对象,并将该对象的原型设置为该函数的[[Prototype]]属性。然后,该函数内部的this关键字将指向这个新创建的对象,并在函数执行完毕后返回该对象。因此,虽然这样的函数不是构造函数,但是它们仍然可以使用new关键字来创建新的对象
- JS中存在一些不完整的构造函数,比如Symbol和BigInt,它们虽然是构造函数,但不能使用new关键字
基本数据类型
null
:表示不存在,是程序级别、意料之中的没有值,如果要给某个变量或属性赋这样一个值,通常用nullundefined
:表示未定义,是系统级别、意料之中或类似错误的没有值String
:表示文本值的字符序列Number
:表示数字Boolean
:表示布尔值Symbol
:它没有字面量语法,只能通过Symbol()获取,返回唯一值,作为对象属性标识符是它唯一的用途BigInt
:用于创建大于2^53-1的数字,可以用整数字面量+n的方式定义
复杂数据类型
全局属性
NaN
:表示非数字的值Infinity
:表示无穷大globalThis
:任何上下文中引用全局对象的标准方式undefined
:表示未定义,是系统级别、意料之中或类似错误的没有值
全局对象
函数对象
- 构造函数对象
Function
:Function是js中万物之源,所有构造函数,包括它自己都是Function的实例Object
:用于创建对象的构造函数。用于存储各种键值集合和更复杂的实体String
:表示和操作字符序列Number
:表示和操作数值Boolean
:表示和操作布尔值Symbol
:表示和操作Symbol类型的值BigInt
:表示和操作BigInt类型的值Date
:日期对象RegExp
:正则对象,用于将文本与一个模式匹配Promise
:用于表示一个异步操作的最终完成或失败及其结果值Generator
:用于生成器函数返回并且它符合可迭代协议和迭代器协议AsyncFunction
:为异步函数提供方法,每个异步函数都是AysncFunction对象GeneratorFunction
:为生成器函数提供方法,每个生成器函数都是GeneratorFunction对象AsyncGeneratorFunction
:为异步生成器函数提供方法,每个异步生成器函数都是AsyncGeneratorFunction对象ArrayBuffer
:用于表示通用的,固定长度的原始二进制数据缓冲区SharedArrayBuffer
:类似于ArrayBuffer,区别是,它不能被转移DataView
:视图对象,它是从ArrayBuffer中读写多种数值类型的底层接口Proxy
:用于创建一个对象的代理,从而实现基本操作的拦截和自定义集合
:支持在单个变量名下存储多个元素,js数组中每个元素可以表示所有数据类型键值对
:Map、Set、WeakMap、WeakSet错误
:当运行时错误产生时,错误对象会被抛出
- 非构造函数对象
eval()
:计算js字符串,并把它作为js代码来执行isFinite()
:检查其参数是否是无穷大isNaN()
:检查其参数是否是非数字值parseFloat()
:解析一个字符串,并返回一个浮点数parseInt()
:解析一个字符串,并返回一个整数decodeURI()
:对encodeURI()函数编码过的URI进行解码decodeURIComponent()
:对encodeURIComponent()函数编码的URI进行解码encodeURI()
:把字符串作为URI进行编码encodeURIComponent()
:把字符串作为URI进行编码,与 encodeURI() 相比,此函数会编码更多的字符
非函数对象
Math
:拥有一些数学常数属性和数学函数方法JSON
:操作JSON对象Atomics
:提供了一组静态方法对sharedArrayBuffer和ArrayBuffer对象进行原子操作Reflect
:提供拦截JS操作的方法,这些方法与proxy相同Intl
:是ES国际化API的命名空间WebAssembly
: 所有webAssembly(一种新的编码方式)相关功能的命名空间
类型转换
JS是一个弱类型语言,这意味着你经常可以使用与预期类型不同类型的值,为此,JS定义了隐式类型转换规则和强制类型转换规则,隐式转换就是不需要人为控制的(语言为你自动转换为正确的类型),这种转换是临时的,并不会对原数据造成影响,而强制转换是通过方法代码控制的。不管是隐式转换还是强制转换,它们转换的结果是一致的,实际上,隐式转换底层也是强制转换实现的,即调用函数进行了转换。
隐式转换举例:+、-、*、/、%运算时,三目运算符中、循环语句中、[for...in]循环的object参数、Array方法的this值、Object方法的参数(如Object.keys())、访问基本类型的属性时。
强制转换举例:调用Number()、String()、Boolean()函数时。
转换为number
- 对于 Number 则总是返回自己
- undefined 变成了 NaN
- null 变成了 0
- true 变成了 1;false 变成了 0
- 字符串通过解析来转换。如果解析失败,返回的结果为 NaN
- BigInt 抛出 TypeError,以防止意外的强制隐式转换损失精度
- Symbol 抛出 TypeError
- 对象首先按顺序调用 [@@toPrimitive]()(hint为"number" )、valueOf() 和 toString() 方法将其转换为原始值。然后将生成的原始值转换为数值
转换为string
- 字符串按原样返回
- undefined 转换成 "undefined"
- null 转换成 "null"
- true 转换成 "true";false 转换成 "false"
- 使用与 toString(10) 相同的算法转换数字
- 使用与 toString(10) 相同的算法转换 BigInt
- Symbol 抛出 TypeError
- 对象通过依次调用 [@@toPrimitive]()(hint 为 "string")、toString() 和 valueOf() 方法将其转换为原始值。然后将生成的原始值转换为一个字符串
转换为boolean
除了null、undefined、''、0、NaN、false外,其他所有数据判定结果都为true。
转换为Symbol
- 尝试将一个 symbol 值转换为一个 number 值时,会抛出一个 TypeError 错误 (e.g. +sym or sym | 0)
- 使用宽松相等时,Object(sym) == sym 返回 true
- 这会阻止你从一个 symbol 值隐式地创建一个新的 string 类型的属性名。例如,Symbol("foo") + "bar" 将抛出一个 TypeError (can't convert symbol to string)
- "safer" String(sym) conversion 的作用会像 symbol 类型调用 Symbol.prototype.toString() 一样,但是注意 new String(sym) 将抛出异常
转换为object
- 对象则按原样返回
- undefined 和 null 则抛出 TypeError
- Number、String、Boolean、Symbol、BigInt 等基本类型被封装成其对应的基本类型对象
数据声明
JS中数据的声明有四种:变量声明、函数声明、类声明、模块声明。此外,JS中只有函数有修饰符,这样的修饰符有两个,即*和async/await。
变量声明
声明变量有三种方式:var、let、const。
var
:声明一个函数范围或全局范围的变量let
:声明可重新赋值的块级作用域局部变量const
:声明不可重新赋值或声明的块级作用域局部变量
函数声明
声明函数有三种方式:普通声明、函数表达式,箭头函数。
function fn() {}
const fn = function() {}
const fun = () => {}
函数修饰符有两种:*、async/await,比如下面这些:
- async function
- function*
- async function*
- ......
类声明
声明类方式有一种:class,类没有修饰符。
模块声明
模块的声明方式有导出(export)和导入(import),导出方式分为具名导出、默认导出,导入方式分为具名导入、默认导入、动态导入。
export
- 具名导出:导出单个变量(export const a = x)、导出单个函数(export function a(){})、导出多个数据(export {a,b,c})
- 默认导出:export default abc
import
-
具名导入:import {a,b,c} from 'abc'
-
默认导入:import abc from 'abc'
-
动态导入:用到操作符import()
总结
本文几乎列出了所有关于数据表达的知识结构,但并未详细介绍细节。
在数据类型这块,有很多对象是日常开发几乎用不到的,其中包括一些构造函数对象和非函数对象。
新增的两种基本数据类型(Symbol和BigInt)在实际开发中几乎用不到。