Почему JavaScript обрабатывает операции "плюс" и "минус" между строками и цифрами по-разному?

Я не понимаю, почему JavaScript работает таким образом.

console.log("1" + 1);
console.log("1" - 1);

Первая строка печатает 11, а вторая - 0. Почему JavaScript обрабатывает первый как строку, а второй - как число?

Ответ 1

Конкатенация строк выполняется с помощью +, поэтому Javascript преобразует первый номер 1 в строку и объединяет "1" и "1" , делая "11".

Вы не можете выполнять вычитание по строкам, поэтому Javascript преобразует второй "1" в число и вычитает 1 из 1, что приводит к нулю.

Ответ 2

+ является неоднозначным. Это может означать "конкатенировать" или "добавить". Поскольку одна сторона является строкой, это означает "конкатенация", поэтому результат равен 11 (что, кстати, было одной из моих любимых шуток как маленький ребенок. Это и "1 + 1 = окно", так как визуально показано: │┼│ ニ ⊞)

- однако имеет только одно значение: вычесть. Поэтому он вычитает.

Этот вид проблемы отсутствует в других языках, таких как PHP, где "concatenate" - это . вместо +, не делая никакой двусмысленности. Другие языки, такие как MySQL, даже не имеют оператора конкатенации, вместо этого используют CONCAT(a,b,c...).

Ответ 3

Потому что спецификация явно сообщает об этом. Обратите внимание на разницу между 11.6.1 шагами 5-8 и 11.6.2 шагами 5-7.

11.6.1 - описывает, как работает оператор сложения

1-4....

5. Пусть lprim - ToPrimitive (lval).

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

7. Если Type (lprim) - String или Type (rprim) - String, то

7a. Верните строку, которая является результатом объединения ToString (lprim), а затем ToString (rprim)

8. Верните результат применения операции добавления в ToNumber (lprim) и ToNumber (rprim)

11.6.2 - описывает, как работает оператор вычитания

1-4....

5. Пусть lnum - число (lval).

6. Пусть rnum должно быть числом (rval).

7. Верните результат применения операции вычитания в lnum и rnum

Резюме В случае добавления, если какой-либо из операндов при преобразовании в примитивное значение без каких-либо намеков внезапно становится строкой, второй преобразуется в строку. В случае вычитания оба операнда преобразуются в число.

Ответ 4

+ является оператором сложения для числовых переменных и конкатенационным оператором для строк.

Всякий раз, когда есть строка после +, Javascript будет выбирать + как оператор конкатенации и преобразовывать (набирать) как можно больше терминов вокруг строки, чтобы она могла их конкатенировать. Это просто поведение Javascript. (Если вы попробовали console.log(23 + 2 + "." + 1 + 5 + "02" + 02);, вы получите результат 25.15022. Число 02 было введено в строку 2 перед конкатенированием.

- может быть только оператором вычитания, поэтому при задании строки он будет неявно изменять тип строки "1" в числовом 1; если бы он этого не сделал, то нет смысла "1" - 1 иметь смысл. Если вы попробовали console.log(23 + 2 + 1 + 5 - "02" + 03);, вы получите 32 - строка 02 преобразуется в число 2. Термин после - должен быть способен преобразовать в число; если вы попробовали console.log(23 - 2 - "." - 1 - 5 - 02 - "02");, вы получите NaN.

Что еще более важно, если вы пробовали console.log(23 + 2 + "." + 1 + 5 - "02" + 03);, он выведет 26.15, где все до - обрабатывается как строка (поскольку она содержит строку ".", а затем термин после - рассматривается как число.

Ответ 5

В JavaScript ** нет специализированного оператора конкатенации строк. Оператор сложения + выполняет либо конкатенацию, либо добавление строки, в зависимости от типа операндов:

"1" +  1  // "11"
 1  + "1" // "11"
 1  +  1  // 2

Нет противоположности конкатенации (я думаю), а оператор вычитания - выполняет только вычитание независимо от типа операндов:

"1" -  1  // 0
 1  - "1" // 0
 1  -  1  // 0
"a" -  1  // NaN

** Оператор . в PHP и операторе & в VB являются выделенными операторами конкатенации строк.

Ответ 6

В соответствии со стандартом EcmaScript 262. Операторы + и - ведут себя по-разному, когда задействованы строки. Первое преобразует каждое значение в строку. Второе преобразует каждое значение в число.

Из стандарта:

Если Type (lprim) - String или Type (rprim) - String, то верните Строка, которая является результатом объединения ToString (lprim), а затем ToString (rprim)

Эти правила подразумевают, что если в выражении имеется строковое значение, все значения, участвующие в операции +, преобразуются в строку. В JavaScript, когда оператор + используется со строками, он объединяет их. Вот почему console.log("5"+1) возвращает "51". 1 преобразуется в строку, а затем "5" + "1" объединяются вместе.

Тем не менее, вышеприведенное правило не применяется к оператору -. Когда вы используете -, все значения преобразуются в номера в соответствии со стандартом (см. Ниже). Поэтому в этом случае "5" преобразуется в 5, а затем 1 вычитается.

Из стандарта:

5 Пусть lnum будет ToNumber (lval).

6 Пусть rnum будет ToNumber (rval).


Определение оператора из стандартного EcmaScript 262.

Оператор +: http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.1 Operator + definition

Оператор -: http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.2 Operator - definition

Ответ 7

Используя плюс и строку "" вы в основном возвращаете строку, потому что выполняете конкатенацию:

typeof ("" + 1 + 0)  // string
typeof (1 + 0)  // number

При использовании - вместо этого вы конвертируете в число, так как возможна конкатенация строк:

typeof ("" - 1 + 0) // number