Blog
Blog copied to clipboard
变量和类型 - 基本类型的装箱与拆箱
基本类型的装箱与拆箱
包装类型
为了便于操作基本类型值,JavaScript定义了 Boolean
、Number
、String
、Symbol
、BigInt
几种包装类型(属于引用类型),每种包装类型都有一种对应的基本类型。
操作基本类型时,JS引擎会自动创建基本类型对应的包装类型。
展开查看模拟代码
const name = 'Logan Lee'
const firstName = name.substr(6)
// 执行时相当于
const name = 'Logan Lee'
const nameObj = new String(name)
const firstName = nameObj.substr(6)
nameObj = null
当然我们也可以自己通过 new
操作符来创建包装类型。
Symbol
、BigInt
不能作构造函数用,可以配合Object
构造函数来创建对应的包装类型。
expect(new Boolean(true)).toBeInstanceOf(Boolean)
expect(new Number(1)).toBeInstanceOf(Number)
expect(new String('Logan')).toBeInstanceOf(String)
expect(Object(Symbol('foo'))).toBeInstanceOf(Symbol)
expect(Object(BigInt(30))).toBeInstanceOf(BigInt)
装箱操作
定义
通过val.prop
或val[expression]
的格式进行属性访问时,如果val
为基本类型变量,则会将其转换为对应的内置对象类型。
上述过程叫做基本数据类型的装箱操作,各类型变量装箱结果见下表。装箱标准定义见 ECMAScript#ToObject。
变量类型 | 装箱结果 |
---|---|
Undefined | 抛出 TypeError 异常 |
Null | 抛出 TypeError 异常 |
Boolean | 返回对应的 Boolean 对象 |
Number | 返回对应的 Number 对象 |
String | 返回对应的 String 对象 |
Symbol | 返回对应的 Symbol 对象 |
BigInt | 返回对应的 BigInt 对象 |
Object | 返回对象本身 |
示例
expect(() => (undefined).x).toThrowError()
expect(() => (null).x).toThrowError()
expect(() => (true).toString()).toBe('true')
expect(() => (1).toFixed(1)).toBe('1.0')
expect(() => ('abc').substr(1)).toBe('bc')
expect(() => (Symbol('foo')).description).toBe('foo')
拆箱操作
在对引用类型(包括)变量进行 数学运算、字符串拼接、模板字符串内计算 等操作时,JS引擎会尝试将其转换为基本类型,这个过程叫做拆箱。
ES6
之前,从引用类型到基本类型的转换会调用引用类型的toString
和valueOf
两个方法,调用顺序根据场景不同而不同,不作赘述。
ES6
之后,统一使用 [Symbol.toPrimitive]
来定义将对象转换为原始值时的行为,函数接收一个字符串参数 hint
,表示要转换到的原始值的预期类型。
const obj1 = {}
const obj2 = {
[Symbol.toPrimitive](hint) {
if (hint === 'number') return 10
if (hint === 'string') return 'Logan'
return 'default'
}
}
expect(+obj1).toBeNaN()
expect(+obj2).toBe(10)
expect(`${obj1}`).toBe('[object Object]')
expect(`${obj2}`).toBe('Logan')
expect('' + obj1).toBe('[object Object]')
expect('' + obj2).toBe('default')