Не могу объяснить эти результаты
Может кто-нибудь объяснить мне, почему эти результаты?
![enter image description here]()
Я знаю, что это не настоящая проблема, но мне интересно узнать.
Спасибо
Ответы
Ответ 1
Это потому, что +
предназначено для добавления чисел и строк, это также унарный оператор. Это также потому, что {}
- это пустой объект и блок-оператор.
Я могу это объяснить.
[] + {}
Оба преобразуются в строки.
[].toString() + {}.toString()
[].toString()
совпадает с [].join('')
, а {}.toString()
- '[object Object]'
, поэтому первый - [object Object]
.
Второй - более запутанный.
{} + []
{}
здесь не интерпретируется как объект, интерпретируется как пустой блок. Таким образом, код внутри запускается. Там нет ничего внутри, поэтому он ничего не делает, затем выполняется следующее утверждение: +[]
. Это преобразует массив в int, который сначала преобразует его в строку, чем его.
{} + [] => +[] => +([].toString()) => 0
Если вы введете {}
в скобки, это будет то же самое, что и первый.
({}) + [] => '[object Object]'
Ответ 2
Из здесь, относящийся к this
-
[] + []
При использовании оператора сложения правый и правый операнды сначала преобразуются в примитивы (§11.6.1). Согласно §9.1, преобразование объекта (в данном случае массива) в примитив возвращается его значение по умолчанию, которое для объектов с допустимым методом toString()
является результатом вызова object.toString()
(§8.12.8). Для массивы это то же самое, что и вызов array.join()
([§15.4.4.2] [4]). Объединение пустого массива приводит к пустой строке, поэтому шаг 7 оператор сложения возвращает конкатенацию двух пустых строк, который является пустой строкой.
-
[] + {}
Подобно [] + []
, оба операнда сначала преобразуются в примитивы. Для "Объектных объектов" (§15.2) это снова является результатом вызов object.toString()
, который для объектов с ненулевым, не undefinedявляется "[object Object]"
([§15.2.4.2] [5]).
-
{} + []
{}
здесь не анализируется как объект, а вместо этого как пустой блок ([§12.1] [6]), по крайней мере, пока вы не заставляете это выражение будет выражением, но об этом позже). Возврат значение пустых блоков пусто, поэтому результатом этого утверждения является так же, как +[]
. Унарный оператор +
([11.4.6] [7]) возвращает ToNumber(ToPrimitive(operand))
. Как мы уже знаем, ToPrimitive([])
- пустая строка, и согласно [§9.3.1] [8] ToNumber("")
равно 0.
-
{} + {}
Как и в предыдущем случае, первый {}
анализируется как блок с пустым возвращаемым значением. Опять же, +{}
совпадает с ToNumber(ToPrimitive({}))
, а ToPrimitive({})
- "[object
Object]"
(см. [] + {}
). Итак, чтобы получить результат +{}
, мы должны примените ToNumber
к строке "[object Object]"
. Когда шагов из [§9.3.1] [9], получаем NaN
в результате:
Если грамматика не может интерпретировать String как расширение StringNumericLiteral, то результат [ToNumber] [10] NaN.
-
Array(16).join("wat" - 1)
В соответствии с [§15.4.1.1] [11] и [§15.4.2.2] [12], Array(16)
создает новый массив длиной 16. Чтобы получить значение аргумента для соединения, [§11.6.2] [13] шаги №5 и №6 показывают, что мы должны преобразовать оба операндов к числу с помощью ToNumber
. ToNumber(1)
является просто 1 ([§9.3] [14]), тогда как ToNumber("wat")
снова NaN
в соответствии с [§9.3.1] [15]. Следуя шагу 7 пункта [11.6.2] [16], [§11.6.3] [17] диктует, что
Если один из операндов NaN, результат NaN.
Итак, аргумент Array(16).join
равен NaN
. Следуя §15.4.4.5 (Array.prototype.join
), мы должны называть ToString
аргументом, который является "NaN"
([§9.8.1] [18]):
Если m NaN, верните строку "NaN"
.
Следуя шагу 10 из [15.4.4.5] [19], мы получаем 15 повторений конкатенации "NaN"
и пустую строку, которая равна результату вы видите. При использовании "wat" + 1
вместо "wat" - 1
в качестве аргумент, оператор сложения преобразует 1
в строку вместо преобразование "wat"
в число, поэтому оно эффективно вызывает Array(16).join("wat1")
.