直接赋值字符串和new String()的区别
创建一个字符串
JS 中创建字符串的方法主要有三种:
- 字符串字面量
const str = 'foo';
- New String 实例化
const str = new String("foo");
- String 构造函数转换
const str = String('foo')
;
但是三者之前的区别我们很多时候并没有探究,只不过进行’==’比较时这些知识却显得尤为重要;
结论:
- 通过 String 构造函数转换的字符串和字符串字面量都是
primitive
值(原生值、基本数据类型); primitive 值并不会拥有自己的属性与方法。- 通过 New String 来实例化的是一个 String 对象,成为了内置属性
[[PrimitiveValue]]
,String 的实例享有 String.prototype 上所有的方法.
结论与悖论
简单来看个例子
1 | var a = 'foo'; |
从 a 和 c 的输出以及
typeof a
、typeof b
的值我们可以很简单验证结论(1)中通过 String 构造函数转换的字符串和字符串字面量都是
primitive
值(原生值、基本数据类型);b 的输出
typeof b
的值可以验证结论(2)中通过 New String 来实例化的是一个 String 对象,成为了内置属性
[[PrimitiveValue]]
;从
b.charAt
可以验证结论(2)中String 的实例享有 String.prototype 上所有的方法.
a.charAt
却和结论(1)中primitive 值并不会拥有自己的属性与方法。相悖
我们在结论中说到 primitive 值并不会拥有自己的属性与方法。但是我们开发时经常会直接使用字面量变量的方法,这不是自相矛盾了么?
悖论解释
每当我们尝试访问一个
primitive
值的属性时,JS 引擎内部会调用一个内置[[toObject]]
方法,
例子中字面量的’foo’转为一个[[PrimitiveValue]]
临时的’foo’ String 对象,
然后从其原型链中尝试查找需要访问的属性,使用结束后再释放掉这个 String 对象。
[[toObject]]
规则
(ECMA-262/5.1 Edition)[https://262.ecma-international.org/5.1/#sec-9.9]
该逻辑适用于所有 primitive 类型的字面值(Undefined, Null, Boolean, String, Number)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Droplets!
评论