包装对象的概念

undefined 特殊值
null
object 复合类型
boolean
原始类型(primitive value)
这五种原始类型的值,都有对应的包装对象(wrapper object)
所谓“包装对象”指的是这些值在需要时,会自动产生的对象
string
number
bigint
symbol

包装对象类型 - 图1

上面示例中,字符串 hello 执行了 charAt() 方法。但是,在 JavaScript 语言中,只有对象才有方法,原始类型的值本身没有方法。这行代码之所以可以运行,就是因为在调用方法时,字符串会自动转为包装对象,charAt() 方法其实是定义在包装对象上。这样的设计大大方便了字符串处理,省去了将原始类型的值手动转成对象实例的麻烦。五种包装对象之中,symbol 类型和 bigint 类型无法直接获取它们的包装对象(即 Symbol() 和 BigInt() 不能作为构造函数使用),但是剩下三种可以

  • Boolean()
  • String()
  • Number()

以上三个构造函数,执行后可以直接获取某个原始类型值的包装对象

包装对象类型 - 图2

上面示例中,s 就是字符串 hello 的包装对象,typeof 运算符返回 object,不是 string,但是本质上它还是字符串,可以使用所有的字符串方法。注意,String() 只有当作构造函数使用时(即带有new命令调用),才会返回包装对象。如果当作普通函数使用(不带有 new 命令),返回就是一个普通字符串。其他两个构造函数 Number() Boolean() 也是如此

包装对象和字面量类型

由于包装对象的存在,导致每一个原始类型的值都有包装对象和字面量两种情况

包装对象类型 - 图3

为了区分这两种情况,TypeScript 对五种原始类型分别提供了大写和小写两种类型。其中,大写类型同时包含包装对象和字面量两种情况,小写类型只包含字面量,不包含包装对象

包装对象类型 - 图4

建议只使用小写类型,不使用大写类型。因为绝大部分使用原始类型的场合,都是使用字面量,不使用包装对象。而且,TypeScript 把很多内置方法的参数,定义成小写类型,使用大写类型会报错

包装对象类型 - 图5

上一小节说过,Symbol()BigInt() 这两个函数不能当作构造函数使用,所以没有办法直接获得 symbol 类型和 bigint 类型的包装对象,除非使用下面的写法。但是,它们没有使用场景,因此 Symbol 和 BigInt 这两个类型虽然存在,但是完全没有使用的理由

包装对象类型 - 图6