Fun with Array.prototype.fill()
Andrey Smolko
Posted on June 25, 2024
Recently, I came across the following code snippet:
const arr = new Array(2).fill([])
arr[0].push(1)
arr[0] === arr[1] // true or false?
The correct answer is true.
Both elements at indexes 0 and 1 contain the same mutable value - empty array which was passed as an argument the the method.
See the description from the ECMAScript specification:
Array.prototype.fill() expects in its first parameter an already defined value and then just set the same value as "number"-keyed property values (step 11b).
This definitely sounds like a challenge for JS geeks. Is it possible to use Array.prototype.fill() in such a way that each element in the resulting array has its own empty array?
Something like that:
const arr = new Array(2).fill([])
arr[0].push(1)
arr[0] === arr[1] // false
arr[0].length //1
arr[1].length //0
To achieve this, I’d use the insight provided by step 11b from the specification:
b. Perform ? Set(O, Pk, value, true).
That statement is straightforward: it sets the value (value) of a specific property key (Pk) of an object (O). JavaScript has a feature that can intercept and redefine fundamental operations for that object. It's called a Proxy!
Let's use a Proxy object and redefine an array set operation to solve our challenge:
const handler = {
set(obj, prop, value) {
//assign a new "instance" of empty array to the properties
obj[prop] = [...value]
return true
},
}
// Proxy cracks the challenge!
const arr = [...new Proxy(Array(2), handler).fill([])];
arr[0].push(1)
arr[0] === arr[1] // false
arr[0].length //1
arr[1].length //0
Solved!
Posted on June 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024