Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Array.from() return the first element undefined?

When I do

const arrayLike = { 1:'foo', 2:'bar', length:2 };
Array.from(arrayLike);

I get

[ undefined, 'foo' ]

When I do

const arrayLike = { 1:'foo', 2:'bar', length:3 };
Array.from(arrayLike)

I get

[ undefined, 'foo', 'bar' ]
  • Why do I not see bar when I set the length?
  • Why do I see only my elements only when I hard-set the length to 3?
  • Why is the first element showing up as undefined?
like image 819
NO WAR WITH RUSSIA Avatar asked Dec 24 '22 16:12

NO WAR WITH RUSSIA


2 Answers

Array's are 0 indexed in JavaScript

All of these questions are answered pretty simply. Array.from assumes that the array-like object you're giving it is zero-indexed. If it isn't you'll get an array that is zero-indexed with all elements that aren't set, including 0 set to undefined. So in your example,

const arrayLike = { 1:'foo', 2:'bar', length:2 };
Array.from(arrayLike);

Is essentially the same as,

const arrayLike = { 0:undefined, 1:'foo', 2:'bar', length:2 };
Array.from(arrayLike);

Because the length is less than the max elements, it essentially stops iterating at that point and the false-length functions as a truncation. What you want is likely,

const arrayLike = { 0:'foo', 1:'bar', length:2 };
Array.from(arrayLike);

Or if you're getting the Array-like from a source that is 1-indexed, set length appropriately so as not to lose the last element, and then ditch the first element from the result (the equivalent of shift).

const arrayLike = { 1:'foo', 2:'bar', length:3 };

let arr = Array.from(arrayLike).splice(1);

let arr = Array.from(arrayLike);
arr.shift();


let [, ...arr] = Array.from(arrayLike);
like image 188
NO WAR WITH RUSSIA Avatar answered Jan 08 '23 08:01

NO WAR WITH RUSSIA


Array.from(obj) does not return undefined, it returns a new array using properties from a given array-like object obj.

And the default values of each index position created is undefined when not given.

The undefined value you are seeing is at index 0 of the created array.

Anyways, it is not a problem, you can still access the indexes 1 and 2 and they will return the values you expect them to return.

You can also verify the default behavior of created arrays with:

console.log(new Array(10))

which logs (index positions 0..9) (length 10):

[undefined x 10]

In JavaScript, you will not see any array with the first index other than 0. Independently how the array was created.


Another alternative to what you are doing is to set the prototype:

const arrayLike = { 1:'foo', 7:'bar' };

//Dynamic set the length
arrayLike.length = Math.max(...Object.keys(arrayLike)) + 1;

//Get built-in features of Array to your arrayLike
Object.setPrototypeOf(arrayLike, Array.prototype);

//Do something
arrayLike.forEach((x, i) => console.log("%i: %s", i, x))
like image 34
Washington Guedes Avatar answered Jan 08 '23 09:01

Washington Guedes