Negative indexing addresses array items from the end: -1 means the last item. JavaScript arrays do not support it natively, but a Proxy can add the behavior. section 8.2.4
A Proxy’s get and set traps convert the property key to a number. For a negative index, they add it to the array’s length; nonnegative indexes pass through unchanged. The same mapping lets you read and modify items. section 8.2.4
Reach the last item
Instead of ninjas[ninjas.length - 1], use proxiedNinjas[-1]. The proxy factory checks that its input is an array before creating the proxy. section 8.2.4
Listing 8.12. Negative array indexes with proxies
function createNegativeArrayProxy(array){
if (!Array.isArray(array)) { #A
throw new TypeError('Expected an array'); #A
} #A
return new Proxy(array, { #B
get: (target, index) => { #C
index = +index; #D
return target[index < 0 ? target.length + index : index]; #E
},
set: (target, index, val) => { #F
index = +index;
return target[index < 0 ? target.length + index : index] = val;
}
});
}
const ninjas = ["Yoshi", "Kuma", "Hattori"]; #G
const proxiedNinjas = createNegativeArrayProxy(ninjas); #H
assert(ninjas[0] === "Yoshi" && ninjas[1] === "Kuma" #I
&& ninjas[2] === "Hattori", #I
"Array items accessed through positive indexes"); #I
#I
assert(proxiedNinjas[0] === "Yoshi" && proxiedNinjas[1] === "Kuma" #I
&& proxiedNinjas [2] === "Hattori", #I
"Array items accessed through positive indexes on a proxy"); #I
assert(typeof ninjas[-1] === "undefined" #J
&& typeof ninjas[-2] === "undefined"
&& typeof ninjas[-3] === "undefined",
"Items cannot be accessed through negative indexes on an array");
assert(proxiedNinjas[-1] === "Hattori" #K
&& proxiedNinjas[-2] === "Kuma"
&& proxiedNinjas[-3] === "Yoshi",
"But they can be accessed through negative indexes");
proxiedNinjas[-1] = "Hachi"; #L
assert(proxiedNinjas[-1] === "Hachi" && ninjas[2] === "Hachi", #L
"Items can be changed through negative indexes"); #L
See the complete proxy factory, including its array check and read and write traps. section 8.2.4
