user1533299 user1533299 - 1 month ago 10
Javascript Question

JS: is it possible to define getter functions on array members?

I haven't found any information on this topic so forgive me please if this is a very weird question.

I know JS allows to define properties as accessors meaning they fire a getter or a setter function when used.

My question is whether the same can be done to array members.

For example, I want a setter function to fire when assigning like this:

myObj[2] = 2 /* set function(value, index) { console.log(value + index) } */


If this is not possible, are there any other ways one can extend the [] operation?

Answer

Basically unless you subclass an array you can not.

Even if you subclass, arrays are much more dynamic than objects. Unlike objects they get items added and removed all the time and you have to be able to dynamically attach getters and setters to each property (key) along with the added item. Not practical. If an array is sub-classed you may modify it's length property with getters and setters and try to watch the array from the changes to it's length property but this requires a lot of array diffing.

I guess with the arrays it's best to use ES6 Proxy object. You might do it as follows;

function ProxyMaker(a){
  return new Proxy(a, { get: function(target, property, receiver) {
                               console.log(target+"'s "+property+" property has been accessed");
                               return target[property];
                             },
                        set: function(target, property, value, receiver) {
                               console.log(target+"'s "+property+" property has been modified");
                               return target[property] = value;
                             },
                        has: function(target, property) {
                               console.log(target+"'s "+property+" property has been checked");
                               return Reflect.has(target, property); // 10x to @Bergi
                             }
                      });
}

var p = ProxyMaker([]);
p[0] = 1;
p[0];
p.push(10);
p.unshift(7);
console.log(JSON.stringify(p))