Почему использование унарного оператора + в массиве дает противоречивые результаты в javascript?
Я тестировал преобразование значений в целое число в javascript и печатал вывод в консоли, когда сталкивался с этим странным поведением.
console.log(+[]) ==> 0
console.log(+[123]) ==> 123
console.log(+['123']) ==> 123
console.log(+[123, 456]) ==> NaN
console.log(+['123asdf']) ==> NaN
Я думал, что значения были преобразованы с помощью parseInt, но оказалось, что это было не так. Я перешел в таблицу преобразования javascript http://www.w3schools.com/js/js_type_conversion.asp
Это дает мне более полное представление о том, как выполняются преобразования. В соответствии с этой таблицей
[] => 0
[20] => 20
[10,20] => NaN
["twenty"] =>NaN
["ten","twenty"] => NaN
Таким образом, они берут первое значение массива и преобразуют его, используя указанные правила. Правила parseInt не применяются.
Я протестировал, чтобы прийти к такому выводу. Вы можете вложить в нее все, что хотите, это даст вам тот же результат.
console.log(+[[[[[[[[[[[10]]]]]]]]]]]) => 10
Итак, тогда я подумал, хорошо, если это случай
console.log(+[undefined]) will return NaN
console.log(+[null]) will return 0
console.log(+[false]) will return 0
это значения, ожидаемые от таблицы преобразования javascript, до целого числа, но оказываются
console.log(+[undefined]) => 0
console.log(+[null]) => 0
console.log(+[false]) => NaN
Последнее самое странное, потому что false преобразуется в 0, а не в NaN.
Может ли кто-нибудь объяснить странное поведение или объяснить, как это преобразование выполняется?
Ответы
Ответ 1
Оператор Unary + использует абстрактную операцию ToNumber.
абстрактная операция ToNumber, когда применяется к объектам, вызывает метод toString
объекта (посредством [[DefaultValue]]
внутренний метод), а затем повторно применяет операцию ToNumber в результирующем строчном представлении.
Интересным здесь является метод Array toString
. Обратите внимание, что [false].toString()
сильно отличается от [undefined].toString()
или [null].toString()
. Когда мы проверяем спецификацию Array.prototype.toString
, мы видим, что внутри она использует Array.prototype.join
. Шаг 8 алгоритма join
гласит:
- Если element0 является
undefined
или null
, пусть R - пустая строка; в противном случае пусть R - ToString (element0).
Таким образом, любой массив, содержащий один null
или undefined
, строит на пустую строку (номер ToNumber - ifies на 0
), в то время как другие значения будут привязаны к какой-либо другой строке (которая будет затем number-ify до NaN
, если строка не является числовой).
+[undefined]
совпадает с +""
, а +[false]
совпадает с +"false"
.