1 回答

TA貢獻1853條經(jīng)驗 獲得超18個贊
從根本上說,因為規(guī)范是這樣說的:
字符串值
原始值是零個或多個 16 位無符號整數(shù)值的有限有序序列
該規(guī)范還定義了 String 對象,與原始字符串不同。(類似地,還有原始number、boolean和symbol類型,以及 Number 和 Boolean 和 Symbol 對象。)
原語字符串遵循其他原語的所有規(guī)則。在語言級別上,它們的處理方式與原始數(shù)字和布爾值完全相同。出于所有意圖和目的,它們都是原始值。但是正如您所說,如果a = b從字面上制作字符串的副本b并將該副本放入a. 實現(xiàn)不必這樣做,因為原始字符串值是不可變的(就像原始數(shù)值一樣)。您不能更改字符串中的任何字符,只能創(chuàng)建一個新字符串。如果字符串是可變的,則實現(xiàn)時必須復制一份a = b(但如果它們是可變的,則規(guī)范會以不同的方式編寫)。
請注意,原始字符串和 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 對象)以及說明何時創(chuàng)建原語的臨時對象版本的規(guī)則使得在原語上定義方法成為可能。當你這樣做時:
console.log("example".toUpperCase());
在規(guī)范術(shù)語中,創(chuàng)建一個 String 對象(通過GetValue 操作),然后toUpperCase在該對象上查找屬性并(在上面)調(diào)用。因此,原始字符串從和獲取它們的toUpperCase(和其他標準方法)。但是除非在某些邊緣情況下,否則代碼無法訪問創(chuàng)建的臨時對象,并且 JavaScript 引擎可以避免在這些邊緣情況之外創(chuàng)建對象。這樣做的好處是可以在原始字符串中添加和使用新方法。String.prototypeObject.prototypeString.prototype
1“什么邊緣情況?” 我聽到你問。我能想到的最常見的一種方法是當您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 引擎被迫創(chuàng)建 String 對象,因為this在松散模式下不能是原語。
嚴格模式可以避免創(chuàng)建對象,因為在嚴格模式下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
添加回答
舉報