为什么有两种JavaScript字符串?

时间:2011-04-01 13:54:36

标签: javascript string

这个只是刺伤了我。我不知道所有浏览器是否都是这种情况(我没有任何其他有能力的浏览器进行测试),但至少Firefox有两种字符串对象。

打开Firebugs控制台并尝试以下操作:

>>> "a"
"a"
>>> new String("a")
String { 0="a"}

正如您可以直观地观察到的那样,Firefox以不同的方式对待new String("a")"a"。否则,两种字符串似乎表现相同。例如,有证据表明两者都使用相同的原型对象:

>>> String.prototype.log = function() { console.log("Logged string: " + this); }
function()
>>> "hello world".log()
Logged string: hello world
>>> new String("hello world").log()
Logged string: hello world
显然,两者都是一样的。也就是说,直到你要求输入类型。

>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"

我们还可以注意到,当this是一个字符串时,它始终是对象形式:

>>> var identity = function() { return this }
>>> identity.call("a")
String { 0="a"}
>>> identity.call(new String("a"))
String { 0="a"}

进一步说,我们可以看到非对象字符串表示不支持任何其他属性,但对象字符串会:

>>> var a = "a"
>>> var b = new String("b")
>>> a.bar = 4
4
>>> b.bar = 4
4
>>> a.bar
undefined
>>> b.bar
4

另外,有趣的事实!您可以使用toString()函数将字符串对象转换为非对象字符串:

>>> new String("foo").toString()
"foo"

从未想过调用String.toString()会有用!反正。

所以这些实验都提出了一个问题:为什么JavaScript中有两种字符串?


评论显示每种原始JavaScript类型(包括数字和bool)也是如此。

3 个答案:

答案 0 :(得分:13)

Javascript中有两种类型的字符串 - 文字字符串和String对象。他们的行为有点不同。两者之间的主要区别是您可以向String对象添加其他方法和属性。例如:

var strObj = new String("object mode");
strObj.string_mode = "object"
strObj.get_string_mode = function() { return this.string_mode; }

// this converts it from an Object to a primitive string:
str = strObj.toString();

字符串文字只是暂时转换为String对象以执行任何核心方法。

同样的概念也适用于其他数据类型。 Here's more on primitive data types and objects

修改

如评论中所述,字符串文字不是原始字符串,而是“文字常量,其类型是内置基元[字符串]值”,引用this source

答案 1 :(得分:2)

将字符串值与字符串对象进行比较。

"a"是一个字符串值。

"a" === "a"; // true

new String("a")是一个字符串对象。

new String("a") === new String("a"); // false

这两个字符串。 "a"只获取字符串值“a”,其中new String("a")创建一个新的字符串对象,其内部具有字符串值“a”

答案 2 :(得分:0)

要记住的另一个重要事项如下:

typeof "my-string" // "string"
typeof String('my-string') // 'string'
typeof new String("my-string") // "object". 

因此,在测试参数或变量是否为字符串时,您至少需要执行以下操作。

function isString(arg) {
  if (!arg) {
    return false;
  }
  return typeof arg == "string" || arg.constructor == String;
}

如果从另一个frame / iframe传入String对象,上面的函数仍然会失败。那就是:

frames[0].myStringVar.constructor != frames[1].myStringVar.constructor

这是因为构造函数String对于每个窗口上下文都是不同的。因此,一个万无一失的isString方法将是

function isString(obj) {
   return Object.prototype.toString.call(obj) == "[object String]";
}