Почему пустой тип массива преобразуется в ноль? + []

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

+[]; // 0
Number([]); // 0

Моя первая мысль заключалась в том, что я должен получить NaN, точно так же, как если бы я попытался преобразовать пустой объект в число:

+{}; // NaN
Number({}); // NaN

Я искал об этом некоторое время без каких-либо успехов...

Может кто-нибудь объяснить мне, почему он преобразуется в 0, а не в NaN?

Является ли это стандартным поведением?

Спасибо.

Ответ 1

Вкратце, есть две ключевые точки:

Например, мы можем использовать объект, который определяет метод toString, и возвращает пустую строку с эквивалентным результатом:

var obj = { toString: function () { return "";} };
+obj; //  0
Number(obj); // 0

Это вполне стандартное поведение.

Теперь длинный ответ:

Оба, унарный плюс и конструктор Number в качестве функции внутренне используйте абстрактную операцию ToNumber.

ToNumber будет использовать еще два внутренних операции, ToPrimitive и [[DefaultValue]].

Когда операция ToNumber применяется к объекту, такой пустой массив в вашем примере, он вызывает операцию ToPrimitive, чтобы получить типичное примитивное значение и вызвать ToNumber снова, используя это значение [ 1].

Операция ToPrimitive получает два аргумента: значение (которое является вашим объектом массива) и тип подсказки, который в этом случае является "числом", поскольку мы хотим сделать числовое преобразование.

ToPrimitive вызывает внутренний метод [[DefaultValue]], также с типом подсказок "Число".

Теперь, поскольку тип подсказки мы используем "Number", внутренний метод [[DefaultValue]] теперь попытается вызвать сначала метод valueOf для объекта.

Объекты массива не имеют определенного метода valueOf, метод - это унаследованный от Object.prototype.valueOf, и этот метод просто возвращает ссылку на сам объект.

Так как метод valueOf не привел к примитивному значению, теперь вызывается метод toString, и он создает пустую строку (которая является примитивным значением), тогда операция ToNumber будет пытаться выполните преобразование String-Number и, наконец, закончите с 0 [1].

Но теперь вы можете удивиться, почему пустая строка приводит к нулю?

+""; // 0

Существует полная грамматика, используемая, когда внутренняя операция ToNumber применяется к типу String, StringNumericLiteral.

У него есть некоторые различия между NumericLiteral, и одно из этих различий заключается в следующем:

StringNumericLiteral, пустой или содержащий только пробел, преобразуется в +0.