Home > Back-end >  Why showing empty array error on creating array explicitly by Object.create on reduce function and f
Why showing empty array error on creating array explicitly by Object.create on reduce function and f

Time:02-15

Creating an array with objects of property descriptors like indexed value object

a = Object.create(Array.prototype, {
    0 : { writable : true, configurable : true, value : 1},
    1 : { writable : true, configurable : true, value : 2},
    2 : { writable : true, configurable : true, value : 3},
    3 : { writable : true, configurable : true, value : 4}
});
//Array {0: 1, 1: 2, 2: 3, 3: 4}
//0: 1
//1: 2
//2: 3
//3: 4
//[[Prototype]]: Array(0)

But why it is not behaving like normal array?

Array.isArray(a) //false
a instanceof Array //true
typeof a.reduce == 'function' //true
a.reduce((previous, current)=> previous current)
//Uncaught TypeError: Reduce of empty array with no initial value
    at Array.reduce (<anonymous>)
    at <anonymous>:1:3
for(let i of a){
    console.log(i);
}
//prints nothing

CodePudding user response:

You did not give your array a .length property.

let a = Object.create(Array.prototype, {
    0 : { writable : true, configurable : true, value : 1},
    1 : { writable : true, configurable : true, value : 2},
    2 : { writable : true, configurable : true, value : 3},
    3 : { writable : true, configurable : true, value : 4},
    length: { writable : true, configurable : true, value : 4}
});

The Array.isArray() function returns false because your object is not an instance of Array; it is an object that shares the Array prototype, but it is not an Array instance. Also, as noted in a comment by an esteemed colleague, your properties should also be enumerable.

Adding length will make your .reduce() work, but you still won't have an actual Array; many other things won't work.

CodePudding user response:

It's not working because length is not defined here.
reduce() and for of need length property to work.

a = Object.create(Array.prototype, {
    0 : { writable : true, configurable : true, value : 1},
    1 : { writable : true, configurable : true, value : 2},
    2 : { writable : true, configurable : true, value : 3},
    3 : { writable : true, configurable : true, value : 4}
});
//Array {0: 1, 1: 2, 2: 3, 3: 4}
a.length = 4
//4
for(let i of a)
    console.log(i);
// 1
// 2
// 3
// 4

But it will still not fool the Array.isArray()

Array.isArray(a)
//false


This is because the hidden machanisim of "Execotic Object" Exotic Object can not be created with Object.create() or new Constructor(), this needs to be extended with javascript class to create subclass enter image description here enter image description here link If now index is the word length ArraySetLength function is called and if previous length is writable and new length is greater than previous it will set the length o array as provided and empty cells will be showed as empty by the browser or node.
Esle if new length is smaller it will delete all the element until it encounter an non-configurable element

const arr = [10, 20,30,50]
//undefined
Object.defineProperty(arr,1, {value: 15, configurable : false});
//[10, 15, 30, 50]
arr.length=0
//0
console.log(arr)
//[10, 15]

YouTube video explaination link

  • Related