Может кто-нибудь объяснить мне, почему эти результаты?
Я знаю, что это не настоящая проблема, но мне интересно узнать.
Спасибо
Может кто-нибудь объяснить мне, почему эти результаты?
Я знаю, что это не настоящая проблема, но мне интересно узнать.
Спасибо
Это потому, что +
предназначено для добавления чисел и строк, это также унарный оператор. Это также потому, что {}
- это пустой объект и блок-оператор.
Я могу это объяснить.
[] + {}
Оба преобразуются в строки.
[].toString() + {}.toString()
[].toString()
совпадает с [].join('')
, а {}.toString()
- '[object Object]'
, поэтому первый - [object Object]
.
Второй - более запутанный.
{} + []
{}
здесь не интерпретируется как объект, интерпретируется как пустой блок. Таким образом, код внутри запускается. Там нет ничего внутри, поэтому он ничего не делает, затем выполняется следующее утверждение: +[]
. Это преобразует массив в int, который сначала преобразует его в строку, чем его.
{} + [] => +[] => +([].toString()) => 0
Если вы введете {}
в скобки, это будет то же самое, что и первый.
({}) + [] => '[object Object]'
[] + []
При использовании оператора сложения правый и правый операнды сначала преобразуются в примитивы (§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")
.