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: Разгадка.
Хочется что-то добавить или сказать? Я всегда рад обсудить. Пишите на me@dikmax.name.