Why Object.assign works with an array?

Samrat Saha picture Samrat Saha · Nov 16, 2018 · Viewed 7.2k times · Source

So I was reading an article to clone an object and array. All of them mentioned that Object.assign() can be used to copy an object but no one mentioned that Object.assign() will also work to shallow copy an array.

Could anybody explain how it works?

Code to Explain is in JS Bin : https://jsbin.com/kaqocixize/edit?js,console

Answer

SzybkiSasza picture SzybkiSasza · Nov 16, 2018

JS is prototype-oriented language. That means that every construct in JS is in reality - an object! :)

Objects differ in some metadata, e.g. specific properties. These are usually readonly and there is no easy way of overriding them (e.g. length, name, arguments and many more).

In your case, array can be interpreted as a specific object where length relates to number of array elements and each array element relates to property on the object that uses index as a key:

const array = {
  '0': 'a',
  '1': 'b',
  '2': 'c',
  'length': 3,
};

(that's simplification, as we're still missing generator for iterating over that is usually kept as a Symbol).

The way JS hides these special properties is usually by using Symbols - more on them here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

Because of prototypic nature of JS, however, when using Object.assign, Array is treated as an object and hence, by doing:

Object.assign([],a,['x']); 

you're actually creating a new array AND overriding element 0 with 'x'. That's how this line can be interpreted in object world:

Object.assign({}, {
  '0': 'a',
  '1': 'b',
  '2': 'c',
}, {
  '0': 'x'
});

And that's how x landed as the first index of a new array!

There are, however, some differences in Array implementation between ES5 and ES6 - more on that here: http://2ality.com/2014/05/es6-array-methods.html