Строка буквальная первая или вторая в конкатенации?

В JavaScript есть ли какие-либо обстоятельства, когда существует семантическая разница между этими двумя параметрами?

foo.bar + ''

...а также...

'' + foo.bar

Я бы ожидал, что последний более надежно принудит результат к строке, но я не могу найти никакого обсуждения этого (после большого Googling) и ни одного примера, где это, кажется, имеет значение.

Ответ 1

Они такие же, как другие, о которых уже упоминалось, с дополнительными соображениями, перечисленными @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

Оба они одинаковы.

Существует только разница, если есть другие + (слева или справа). Другими словами:

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

Это не то же самое, что:

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

Ответ 3

Если один из операндов является строкой, на другой будет вызываться valueOf() или toString(), так что да, они точно такие же.

12.8.3 спецификации:

 AdditiveExpression + MultiplicativeExpression
  1. Пусть lref является результатом оценки AdditiveExpression.

  2. Пусть lval be? ПолучитьЗначение (LRef).

  3. Пусть rref является результатом вычисления мультипликативного выражения.

  4. Пусть rval be? ПолучитьЗначение (RREF).

  5. Пусть lprim будет? ToPrimitive (lval).

  6. Пусть rprim be? ToPrimitive (RVAL).

  7. Если Type (lprim) является String или Type (rprim), является String, тогда

    а. Пусть lstr будет? ToString (lprim).

    б. Пусть rstr? ToString (rprim).

    с. Вернуть строку, которая является результатом объединения lstr и rstr

Ответ 4

Вот несколько правил, взятых отсюда

  • Если хотя бы один операнд является объектом, он преобразуется в примитивное значение (строка, число или логическое значение);
  • После преобразования, если хотя бы один операнд является строковым типом, второй операнд преобразуется в строку и выполняется конкатенация;
  • В другом случае оба операнда преобразуются в числа и выполняется арифметическое добавление.

Ответ 5

Нет, нет никакой разницы.

Если foo.bar не является примитивным значением, тогда на него вызывается первое значение valueOf. Если это еще не возвращает примитивное значение, на него вызывается toString. Если это еще не возвращает примитивное значение, запускается ошибка.

Во всем этом объект foo.bar не знает, в каком вызове вызывается значение valueOf или toString. Объект не может различать два упомянутых вами случая. Это даже не должно быть одним из этих двух.

Наконец, нет способа установить ловушку для оператора +, чтобы вы могли знать его операнды.

Вот демонстрация того, как вызываются valueOf и toString в следующем порядке:

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);