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
?
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
?
- Possible duplicate of: How do I create an array in javascript whose index starts from 1 – Washington Guedes Commented Jul 11, 2017 at 18:03
- @WashingtonGuedes nothing to do with array.from. that question is just challenging wanting to implement a 1-index array, not convert a 1-index object to an array. – Evan Carroll Commented Jul 11, 2017 at 18:07
- Still related. Explains the issue of this post. – Washington Guedes Commented Jul 11, 2017 at 18:11
2 Answers
Reset to default 9Array'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);
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))