Javapcript Proxy running . get() instead of . set()

Asked

Viewed 57 times

3

I wrote the following minimum code:

const greetings = new Proxy(
  {
    english: {
      well: "Hello ",
      come: "World!"
    },
    portuguese: {
      bem: "Ola",
      bindo: "Mundo!"
    }
  },
  {
    get: (ctx, key) => {
      console.log("Getter called");
      return ctx[key];
    },
    set: (ctx, key, val) => {
      console.log("Setter called");
      ctx[key] = val;
    }
  }
);

greetings.english.well = "Hola"; // (1)
greetings.english.come = "Mundo"; // (2)

console.log(`English wellcome :: ${greetings.english.well} ${greetings.english.come}`);

LOG CONSOLE:

Getter called // (3)
Getter called // (4)
Getter called
Getter called
Wellcome :: Hola Mundo

With the intention of observing the workings of the getters and setters of the new Proxy functionality().

And it actually works well, AS LONG AS the target has only one hierarchy level.

But when one object is placed inside the other, such as well and come is placed within english, that gives problem.

THE PROBLEM:

I hoped that line of code (1) and (2) execute the method .set() of Proxy. However, is executing the .get(), as observable in the console log.

THE EXPECTED:

I hoped the log (3) and (4) print: Setter called, with S set, not with G get.

This happens because the Proxy does not observe that on the line (1) and (2) a set is invoked and not a get.

There’s a way around it?

1 answer

2

I don’t know if I understand the question correctly, but before anything I’m going to make a modification in your code, to visualize the best what’s happening to it.

What I will do is a modification within the advisory methods(traps) get and set in order to show what they are being applied to:

modification in get:

   get: (ctx, key) => {
      console.log(`${key} Getter called`);
      return ctx[key];
   }

modification in set:

   set: (ctx, key, val) => {
      console.log(`${key} Setter called`);
      ctx[key] = val;
   }

In order to display which property they act on:

const greetings = new Proxy(
  {
    english: {
      well: "Hello ",
      come: "World!"
    },
    portuguese: {
      bem: "Ola",
      bindo: "Mundo!"
    }
  },
  {
    get: (ctx, key) => {
      console.log(`${key} Getter called`);
      return ctx[key];
    },
    set: (ctx, key, val) => {
      console.log(`${key} Setter called`);
      ctx[key] = val;
    }
  }
);

greetings.english.well = "Hola"; // (1)
greetings.english.come = "Mundo"; // (2)

console.log(`English wellcome :: ${greetings.english.well} ${greetings.english.come}`);

As you can see when executing the code the result is:

english Getter called
english Getter called
english Getter called
english Getter called
English wellcome :: Hola Mundo

Which means when you do the lines:

greetings.english.well = "Hola"; 
greetings.english.come = "Mundo"; 

The method set to the property english is called twice. And when you do the line:

console.log(`English wellcome :: ${greetings.english.well} ${greetings.english.come}`);

The method set to the property english is called twice more.

According to the object manual Proxy the access methods for the properties are defined english and portuguese of its object. However, the english and portuguese are not covered by the traps defined in the proxy because even being nested are different objects from which the Proxy is applied

If you also want to define access methods for the properties of english and portuguese also create proxies for these objects:

const greetings = new Proxy({
  english: new Proxy({
    well: "Hello ",
    come: "World!"
  }, {
    get: (ctx, key) => {
      console.log(`${key} Getter called`);
      return ctx[key];
    },
    set: (ctx, key, val) => {
      console.log(`${key} Setter called to value ${val}`);
      ctx[key] = val;
    }
  }),
  portuguese: new Proxy({
    bem: "Ola",
    bindo: "Mundo!"
  }, {
    get: (ctx, key) => {
      console.log(`${key} Getter called`);
      return ctx[key];
    },
    set: (ctx, key, val) => {
      console.log(`${key} Setter called to value ${val}`);
      ctx[key] = val;
    }
  })
}, {
  get: (ctx, key) => {
    console.log(`${key} Getter called`);
    return ctx[key];
  }/*, 
     //O setter aqui foi cometado pois parece ser desnecessário
     //pois as propriedades que sefrerão modificações serão well, come, bem e bindo
  set: (ctx, key, val) => {
    console.log(`${key} Setter called`);
    ctx[key] = val;
  }*/
});

greetings.english.well = "Hola";
greetings.english.come = "Mundo";

console.log(`English wellcome :: ${greetings.english.well} ${greetings.english.come}`);

Verbosity problem:

As commented this implementation of nested proxies is difficult to read and conducive to hiding errors. An alternative is to return with the set commented on the previous fragment and make the implementation of english and portuguese the implementation part of greetings.

const english = new Proxy({
  well: "Hello ",
  come: "World!"
}, {
  get: (ctx, key) => {
    console.log(`${key} Getter called`);
    return ctx[key];
  },
  set: (ctx, key, val) => {
    console.log(`${key} Setter called to value ${val}`);
    ctx[key] = val;
  }
});

const portuguese = new Proxy({
  bem: "Ola",
  bindo: "Mundo!"
}, {
  get: (ctx, key) => {
    console.log(`${key} Getter called`);
    return ctx[key];
  },
  set: (ctx, key, val) => {
    console.log(`${key} Setter called to value ${val}`);
    ctx[key] = val;
  }
})

const greetings = new Proxy({
  english: {},
  portuguese: {}
}, {
  get: (ctx, key) => {
    console.log(`${key} Getter called`);
    return ctx[key];
  },
  set: (ctx, key, val) => {
    console.log(`${key} Setter called`);
    ctx[key] = val;
  }
});

greetings.english = english;
greetings.portuguese = portuguese;


greetings.english.well = "Hola";
greetings.english.come = "Mundo";

console.log(`English wellcome :: ${greetings.english.well} ${greetings.english.come}`);

  • I understood! But one Proxy within another seems very verbose and complicated. Do what. That’s what you have, right...

  • Yes it is very verbose, an alternative is to go back with Setter, which has been commented on, and implement the objects separately.

  • @Jhenry take a look at the issue I made.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.