8

下面用示例编号 1 描述了我的问题:

 var myString = new String('foo');

如果我使用console.log(myString); 输出是String { 0="f", 1="o", 2="o"}

和 2 号:

var myString = new String();
myString = "foo";

这里console.log(mystring);只打印foo

这里 number-1 和 number-2 有什么区别?为什么输出不同?

4

3 回答 3

13

这个说法:

var myString = new String('foo');

...创建一个用字符、和初始化的字符串对象foo

这个说法:

var myString = new String();

...创建一个没有字符的字符串对象,但这并不重要,因为这个语句:

myString = "foo";

...丢弃该字符串对象,并用具有这些字符的新原始字符串替换该变量的值。最终结果与以下内容完全相同:

var myString = "foo";

输出console.log不同的原因是提供 的浏览器console.log试图明确其中一个是对象,另一个是原语。

有点令人困惑的是,JavaScript 既有字符串对象又有字符串原语。(它也有数字对象和数字原语。)几乎没有任何理由使用new String,它创建了一个字符串对象;只需使用原语(在您的情况下为文字)即可。相反,有很好的理由使用字符串对象,例如:

console.log(new String("foo") === new String("foo")); // "false"
console.log(new String("foo")  == new String("foo")); // "false"
console.log("foo" === "foo");                         // "true"

因为字符串对象是对象,==并且===比较的是对象引用,而不是字符序列。虽然可能有一些边缘情况是您想要的,但在 99.9% 的情况下,您真正​​想要的是比较这些值。好消息是:

console.log("foo" == new String("foo")); // "true"

...但是如果您使用===不会进行任何类型强制,那将是不正确的。


你可能会问:

因此,如果var myString = "foo"返回一个原语,而不是一个对象,那么它是如何myString.toUpperCase()工作的呢?

好问题:答案是原语被自动提升为对象,以便我们可以进行函数调用。(理论上;在实践中,实现比这更聪明。)

于 2013-06-27T22:06:42.087 回答
2

最好的理解方法是运行这两个语句

console.log(typeof 'foo'); // -> "string"

console.log(typeof new String('foo')); // -> "object"

另外,您将 myString 重新分配给“字符串”而不是 String 对象的第二条语句

于 2013-06-27T22:05:26.557 回答
2
console.log(typeof s_prim); // Logs "string"
console.log(typeof s_obj);  // Logs "object"

区别是微妙的,特别是因为在字符串原语上调用的方法被字符串对象方法包装,所以在功能上它们接近相同。

正如MDN 参考中所指出的,这可能对 eval() 调用很重要。如果在字符串对象上调用,Eval 将返回对象“2 + 2”,如果在原语上调用,则返回 4。

于 2013-06-27T22:07:45.910 回答