logan70 / Blog

写博客的地方,觉得有用的给个Star支持一下~
81 stars 9 forks source link

变量和类型 - 基本类型的装箱与拆箱 #12

Open logan70 opened 4 years ago

logan70 commented 4 years ago

基本类型的装箱与拆箱

包装类型

为了便于操作基本类型值,JavaScript定义了 BooleanNumberStringSymbolBigInt 几种包装类型(属于引用类型),每种包装类型都有一种对应的基本类型。

操作基本类型时,JS引擎会自动创建基本类型对应的包装类型。

展开查看模拟代码 ```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 操作符来创建包装类型。

SymbolBigInt 不能作构造函数用,可以配合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.propval[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之前,从引用类型到基本类型的转换会调用引用类型的toStringvalueOf两个方法,调用顺序根据场景不同而不同,不作赘述。

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')