每个原始类型boolean,number,bigint,string 和symbol 都有一个相关的封装类(Boolean,Number,BigInt,String,Symbol )。在这篇博文中,我们研究这些类有什么用处。
原始类型的封装类
这是一个关于JavaScript原始值的详尽列表。
undefinednull- 布尔
- 数字
- 大字符
- 字符串
- 符号
每个原始类型(除了undefined 和null 的类型)都有一个相应的包装器类。
BooleanNumberBigIntStringSymbol
这些类的主要目的是为原始值提供属性(主要是方法)。我们将在本系列博文的第二篇中看到具体如何操作。这是一个例子。
> 'abc'.toUpperCase === String.prototype.toUpperCase
true
有两种调用包装器类的方法。
-
所有的封装类都可以被函数调用,将一个任意的值转换为该类所代表的原始类型。这是一种转换到原始类型的描述性方式,我推荐这种方式。
-
只有包装类
Boolean,Number, 和String可以通过new进行实例化。这样做(显式)对程序员来说几乎没有用处。
实例化包装器类
封装类Boolean,Number, 和String 可以通过new 来实例化。
> new String('abc') instanceof String
true
也就是说,new String() 包装一个原始字符串并产生一个包装器对象。
封装类BigInt (ES2020)和Symbol (ES6)相对较新,不能被实例化。
> new BigInt(123)
TypeError: BigInt is not a constructor
> new Symbol('MY_SYMBOL')
TypeError: Symbol is not a constructor
通用地包装基元值
除了通过new-调用包装器类来包装基元值之外,我们还可以通过函数调用Object (大多数对象的类)来进行通用包装。
assert.equal(
Object('abc') instanceof String, true
);
assert.equal(
Object(123) instanceof Number, true
);
通过Object() ,我们甚至可以创建BigInt 和Symbol 的实例(尽管这些类不能被new-invoked)。
> Object(123n) instanceof BigInt
true
> Object(Symbol('MY_SYMBOL')) instanceof Symbol
true
顺便说一句,如果Object() 的参数是一个对象,它就会被简单地返回而不做任何改变。
const obj = {};
assert.equal(
Object(obj), obj
);
解除原始值的包装
解除包装对象的通用方法是方法.valueOf() 。
> new String('abc').valueOf()
'abc'
> new Number(123).valueOf()
123
原始值与包装器对象
有趣的是,原始值'abc' 并不是包装器类String 的实例。
> 'abc' instanceof String
false
> new String('abc') instanceof String
true
typeof 这也告诉我们, 是原始值,但 是一个对象。'abc' new String('abc')
> typeof 'abc'
'string'
> typeof new String('abc')
'object'
也就是说,原始类型的值与相关包装器类的实例不同。在日常编程中,我假装包装器对象并不存在。它们在引擎盖下被使用,但在其他地方很少有用。
更多关于原始值和对象的区别的信息,请参见"不耐烦的程序员的JavaScript"。
函数调用包装器类
函数调用封装类为我们提供了一种将任意值转换为基元的描述性方法。
> Boolean(0)
false
> Number('123')
123
> BigInt(123)
123n
> String(123)
'123'
Symbol() 有一个特殊的地位,即它更像是一个符号的工厂函数(其参数是描述所创建的符号的字符串),而不是一个转换函数。
> typeof Symbol('MY_SYMBOL')
'symbol'
函数--将一个封装类应用于它的一个实例,解除该实例的封装。
> Number(new Number(123))
123
> String(new String('abc'))
'abc'