1、来看一些奇怪的现象
-
console.log("ABC" instanceof String)
>>false
也就是说字符串的字面量并不是String
对象的实例 -
console.log("ABC" instanceof Object)
>>false
字符串的字面量甚至不是个Object
的实例 -
console.log("ABC".indexOf === String().indexOf)
>>true
-
console.log("ABC". includes === String(). includes)
>>true
...
这就很奇怪了为什么字符串的字面量不是String
对象(甚至不是个对象)的实例却拥有String
的方法呢?
2、复习下基本数据类型
在 JavaScript 中,基本类型(基本数值、基本数据类型)是一种既非对象也无方法或属性的数据。有 7 种原始数据类型:
以上摘自 MDN
-
typeof 'ABC'
>>string
-
typeof new String('ABC')
>>object
运行以上代码可以发现,字面量字符串确实只是基本类型string
且与String
实例对象是不同的。
3、既然是基本类型如何做到拥有String
对象的方法呢?
基本类型没有方法,但仍然表现得像有方法一样。当在基本类型上访问属性时,JavaScript 自动将值装入包装器对象中,并访问该对象上的属性。例如,
"foo".includes("f")
隐式创建了一个String
包装对象,并在该对象上调用String.prototype.includes()
。这种自动装箱行为在 JavaScript 代码中是无法观察到的,但却是各种行为的一个很好的心理模型——例如,为什么“改变”基本类型不起作用(因为str.Foo = 1
不是赋值给str
本身的Foo
属性,而是赋值给了一个临时包装器对象)
以上摘自 MDN
其实MDN中已经解释得很清楚了,当访问访问属性时其实是访问量一个临时被包装成 String
实例的对象。
这种隐式自动装箱行为在其他几个有对应包装类型的基本类型中也会发生:
类型 | 包装器对象 |
---|---|
null |
N/A |
undefined |
N/A |
boolean |
Boolean |
number |
Number |
bigInt |
BigInt |
string |
String |
symbol |
Symbol |
根据以上我们其实可以得出结论:
JavaScript 中除了 null
和 undefined
一切皆可以表现为对象。