Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Arrays. Why does concatenating an empty array with a populated array result in a string? [duplicate]

I was working on a problem for flattening arrays. I came across something really strange and can't seem to find an answer online about it.

Why does

[] + [1,2] = '1,2'

I can't seem to wrap my head around why adding an empty array to a populated one results in a string with the contents of the populated array.

What is happening behind the scenes that causes this?

Example from my code:

arr = [1, [2], [3, 4]];
arr.reduce(flatten, []); // [1, 2, 3, 4]

function flatten(a, b) {
    return a.concat(b);
}

As far as I understand, reduce will set '[]' as the 'initial value' and thus for each element in the original array it will concatenate it with an empty array thus "flattening" the array.

like image 969
vampiire Avatar asked Feb 05 '23 13:02

vampiire


2 Answers

When you use + between objects (arrays are objects), JavaScript calls toString() and/or valueOf() internally.

var coercion1 = {} + {foo: 'Foo', bar: 'Bar'},
    coercion2 = [] + ['foo', 'bar'];

console.log(coercion1);
console.log(coercion2);

This is the same thing as:

var coercion1 = "".concat({}.toString(), {foo: 'Foo', bar: 'Bar'}.toString()),
    coercion2 = "".concat([].toString(), ['foo', 'bar'].toString());

console.log(coercion1);
console.log(coercion2);

Which is, again, the same thing as:

var coercion1 = "".concat({}.valueOf(), {foo: 'Foo', bar: 'Bar'}.valueOf()),
    coercion2 = "".concat([].valueOf(), ['foo', 'bar'].valueOf());

console.log(coercion1);
console.log(coercion2);

To convert an object to a string, JavaScript takes these steps:

  • If the object has a toString() method, JavaScript calls it. If it returns a primitive value, JavaScript converts that value to a string (if it is not already a string) and returns the result of that conversion. [...]
  • If the object has no toString() method, or if that method does not return a primitive value, then JavaScript looks for a valueOf() method. If the method exists, JavaScript calls it. If the return value is a primitive, JavaScript converts that value to a string (if it is not already) and returns the converted value.
  • Otherwise, JavaScript cannot obtain a primitive value from either toString() or valueOf(), so it throws a TypeError.

David Flanagan, JavaScript: The Definitive Guide

like image 125
Badacadabra Avatar answered Feb 07 '23 11:02

Badacadabra


This is happening because of JavaScript's implicit type coersion triggered by the + operator. You can't simply perform a + operation on arrays, so they are converted to strings (which contain the comma-separated string-converted values of the array).

like image 35
lxe Avatar answered Feb 07 '23 11:02

lxe