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
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]