JavaScript и приведение типов
Среда, 3 октября 2012

JavaScript прекрасен. Но в нем есть некоторое количество так называемых особенностей, которые делают его чуть менее прекрасным, чем хотелось бы. Например, приведение типов.

[]+[] 
> ""
[]+{}
> "[object Object]"
{}+[]
> 0
{}+{}
> NaN

Почему так? Это кажется бредом, пока не разберешься с системой типов в JavaScript. Ладно-ладно, это кажется бредом в любом случае, но тем не менее попробуем хоть чуть разобраться.

Самое главное, что нужно знать — операция + работает только с примитивными типами. Т.е. что бы вы ни написали, выражение будет приведено к этим типам. Даже больше: если хотя бы один операнд — строка, то и результат будет строкой. Поэтому, чтобы понять причину происходящего выше, нужно узнать, как объекты и массивы приводятся к примитивным типам.

У каждого объекта и массива (ведь массив тоже объект) есть 2 метода: valueOf и toString. И именно они будут использоваться для преобразования типов. Сначала интерпретатор вызывает valueOf, и если он вернул не примитивное значение, то вызывается toString. Теперь нужно выяснить, что же возвращают эти методы у {} и [].

console.log({}.valueOf());  // Возвращает себя
console.log([].valueOf());  // [] (тоже себя)
console.log([].toString()); // ""
console.log({}.toString()); // "[object Object]"

Засада. Каким образом {}+[] дает 0, ведь по логике должно быть "[object Object]"? Ковыряние в спецификации пока ни к чему не привело. Если кто знает правильный ответ, не томите, поделитесь наблюдениями.

Ну и совсем напоследок видео, из-за которого я начал разбираться в этой теме. Посмотрите, не пожалеете.

UPD: Исправлен верхний листинг.

UPD2: Разгадка.

← ОптимизацияAngularJS →

Хочется что-то добавить или сказать? Я всегда рад обсудить. Пишите на me@dikmax.name.