1 回答

TA贡献1853条经验 获得超18个赞
从根本上说,因为规范是这样说的:
字符串值
原始值是零个或多个 16 位无符号整数值的有限有序序列
该规范还定义了 String 对象,与原始字符串不同。(类似地,还有原始number、boolean和symbol类型,以及 Number 和 Boolean 和 Symbol 对象。)
原语字符串遵循其他原语的所有规则。在语言级别上,它们的处理方式与原始数字和布尔值完全相同。出于所有意图和目的,它们都是原始值。但是正如您所说,如果a = b从字面上制作字符串的副本b并将该副本放入a. 实现不必这样做,因为原始字符串值是不可变的(就像原始数值一样)。您不能更改字符串中的任何字符,只能创建一个新字符串。如果字符串是可变的,则实现时必须复制一份a = b(但如果它们是可变的,则规范会以不同的方式编写)。
请注意,原始字符串和 String 对象确实是不同的东西:
const s = "hey";
const o = new String("hey");
// Here, the string `s` refers to is temporarily
// converted to a string object so we can perform an
// object operation on it (setting a property).
s.foo = "bar";
// But that temporary object is never stored anywhere,
// `s` still just contains the primitive, so getting
// the property won't find it:
console.log(s.foo); // undefined
// `o` is a String object, which means it can have properties
o.foo = "bar";
console.log(o.foo); // "bar"
那么为什么要有原始字符串呢?你得问 Brendan Eich(他在 Twitter 上的反应很合理),但我怀疑这是因为等价运算符(==、===、!=和!==)的定义不必是可能被用于其自身目的的对象类型,或用于字符串的特殊情况。
那么为什么要有字符串对象呢?拥有 String 对象(以及 Number 对象、Boolean 对象和 Symbol 对象)以及说明何时创建原语的临时对象版本的规则使得在原语上定义方法成为可能。当你这样做时:
console.log("example".toUpperCase());
在规范术语中,创建一个 String 对象(通过GetValue 操作),然后toUpperCase在该对象上查找属性并(在上面)调用。因此,原始字符串从和获取它们的toUpperCase(和其他标准方法)。但是除非在某些边缘情况下,否则代码无法访问创建的临时对象,并且 JavaScript 引擎可以避免在这些边缘情况之外创建对象。这样做的好处是可以在原始字符串中添加和使用新方法。String.prototypeObject.prototypeString.prototype
¹“什么边缘情况?” 我听到你问。我能想到的最常见的一种方法是当您String.prototype在松散模式代码中添加自己的方法(或类似方法)时:
Object.defineProperty(String.prototype, "example", {
value() {
console.log(`typeof this: ${typeof this}`);
console.log(`this instance of String: ${this instanceof String}`);
},
writable: true,
configurable: true
});
"foo".example();
// typeof this: object
// this instance of String: true
在那里,JavaScript 引擎被迫创建 String 对象,因为this在松散模式下不能是原语。
严格模式可以避免创建对象,因为在严格模式下this不需要是对象类型,它可以是原始类型(在本例中为原始字符串):
"use strict";
Object.defineProperty(String.prototype, "example", {
value() {
console.log(`typeof this: ${typeof this}`);
console.log(`this instance of String: ${this instanceof String}`);
},
writable: true,
configurable: true
});
"foo".example();
// typeof this: string
// this instanceof String: false
添加回答
举报