字符串字面量是串联的第一还是第二?

时间:2018-07-27 19:33:33

标签: javascript

在JavaScript中,这两个选项之间在语义上是否存在差异?

foo.bar + ''

...和...

'' + foo.bar

我希望后者能更可靠地将结果强制转换为字符串,但是我(在经过大量谷歌搜索之后)找不到任何讨论,也找不到任何看起来很重要的例子。

5 个答案:

答案 0 :(得分:15)

两者都一样。

只有其他+(在左侧或右侧)才有所不同。换句话说:

1 + 1 + ''                          // results in '2'

不同于:

'' + 1 + 1                          // results in '11'

答案 1 :(得分:13)

它们与其他人已经提到的相同,并在@Zohaib Ijaz中列出了其他注意事项:

var values = [
  undefined,
  null,
  false,
  true,
  0,
  -1,
  1,
  NaN,
  Infinity,
  '',
  '123',
  'abc123',
  '123abc',
  [],
  [0],
  [1],
  {},
  {a: 1},
  function(){}   
];
var foo = {bar: null};

values.forEach(function(value) {
  foo.bar = value;
  
  console.log("foo.bar + '':", foo.bar + '');
  console.log("'' + foo.bar:", '' + foo.bar);
});

但是,如果您有 2个以上的操作数(如@ibrahim mahrir所述,则存在显着差异

var values = [
  undefined,
  null,
  false,
  true,
  0,
  -1,
  1,
  NaN,
  Infinity,
  '',
  '123',
  'abc123',
  '123abc',
  [],
  [0],
  [1],
  {},
  {a: 1},
  function(){}   
];
var foo = {bar: null};

values.forEach(function(value) {
  foo.bar = value;
  
  console.log("foo.bar + '' + foo.bar:", foo.bar + '' + foo.bar);
  console.log("'' + foo.bar + '':", '' + foo.bar + '');
});

答案 2 :(得分:5)

如果一个操作数是一个字符串,则将valueOf()toString()调用另一个,所以是的,它们是完全相同的。

规范的12.8.3:

 AdditiveExpression + MultiplicativeExpression
     
      
  1. 让lref是评估AdditiveExpression的结果。

  2.   
  3. 让lval是吗? GetValue(lref)。

  4.   
  5. 让rref成为对MultiplicativeExpression求值的结果。

  6.   
  7. 让rval为? GetValue(rref)。

  8.   
  9. 让lprim成为? ToPrimitive(lval)。

  10.   
  11. 让rprim是? ToPrimitive(rval)。

  12.   
  13. 如果Type(lprim)为String或Type(rprim)为String,则然后

         

    a。让lstr成为? ToString(lprim)。

         

    b。让rstr为? ToString(rprim)。

         

    c。返回将lstr和rstr串联的结果的字符串

  14.   

答案 3 :(得分:3)

不,没有区别。

如果foo.bar不是原始值,则首先调用valueOf。如果仍然没有返回原始值,则在其上调用toString。如果仍然没有返回原始值,则会触发错误。

在所有这一切中,foo.bar对象不知道在哪个上下文中valueOftoString被调用。对象无法区分您提到的两种情况。甚至不必是这两个之一。

最后,无法在+运算符上设置陷阱,因此您可以知道其操作数。

以下是如何按此顺序调用valueOftoString的演示:

const foo = { 
    bar: {
        valueOf() {
            console.log('valueOf');
            return this; // not a primitive value, so now toString will be called.
        },
        toString() {
            console.log('toString');
            return "1";
        }
    }
}

console.log(foo.bar + '');
console.log("====");
console.log('' + foo.bar);

答案 4 :(得分:2)

以下是从here

摘录的一些规则
  • 如果至少一个操作数是一个对象,则将其转换为原始值(字符串,数字或布尔值);
  • 转换后,如果至少一个操作数是字符串类型,则将第二个操作数转换为字符串并执行连接;
  • 在其他情况下,两个操作数都转换为数字并执行算术加法。