Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use javascript proxy for nested objects

I have this code in js bin:

var validator = {
  set (target, key, value) {
    console.log(target);
    console.log(key);
    console.log(value);
    if(isObject(target[key])){

    }
    return true
  }
}


var person = {
      firstName: "alfred",
      lastName: "john",
      inner: {
        salary: 8250,
        Proffesion: ".NET Developer"
      }
}
var proxy = new Proxy(person, validator)
proxy.inner.salary = 'foo'

if i do proxy.inner.salary = 555; it does not work.

However if i do proxy.firstName = "Anne", then it works great.

I do not understand why it does not work Recursively.

http://jsbin.com/dinerotiwe/edit?html,js,console

like image 756
Aflred Avatar asked Dec 23 '16 10:12

Aflred


People also ask

Can you nest objects in JavaScript?

Nested objects are objects that are inside another object. You can create nested objects within a nested object. In the following example, Salary is an object that resides inside the main object named Employee . The dot notation can access the property of nested objects.

How do I create a nested object in JavaScript?

Creating Nested Objects in JavaScript Dynamically In ES6, Objects can be created with computed properties. To use a “dynamic” key, you have to use bracket notation: Iterate through the elements of basis . Use the keys to find the corresponding element in nested , and use that as the key in the new object being created.

What is the use of proxy object in JavaScript?

The Proxy object allows you to create an object that can be used in place of the original object, but which may redefine fundamental Object operations like getting, setting, and defining properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs, and so on.

What does a proxy do to the target object Ecmascript?

A proxy allows you to perform meta-programming operations such as intercepting a call to inspect or change an object's property. The original object the proxy will virtualize.


3 Answers

You can add a get trap and return a new proxy with validator as a handler:

var validator = {    get(target, key) {      if (typeof target[key] === 'object' && target[key] !== null) {        return new Proxy(target[key], validator)      } else {        return target[key];      }    },    set (target, key, value) {      console.log(target);      console.log(key);      console.log(value);      return true    }  }      var person = {        firstName: "alfred",        lastName: "john",        inner: {          salary: 8250,          Proffesion: ".NET Developer"        }  }  var proxy = new Proxy(person, validator)  proxy.inner.salary = 'foo'
like image 155
Michał Perłakowski Avatar answered Sep 20 '22 18:09

Michał Perłakowski


A slight modification on the example by Michał Perłakowski with the benefit of this approach being that the nested proxy is only created once rather than every time a value is accessed.

If the property of the proxy being accessed is an object or array, the value of the property is replaced with another proxy. The isProxy property in the getter is used to detect whether the currently accessed object is a proxy or not. You may want to change the name of isProxy to avoid naming collisions with properties of stored objects.

Note: the nested proxy is defined in the getter rather than the setter so it is only created if the data is actually used somewhere. This may or may not suit your use-case.

const handler = {    get(target, key) {      if (key == 'isProxy')        return true;        const prop = target[key];        // return if property not found      if (typeof prop == 'undefined')        return;        // set value as proxy if object      if (!prop.isProxy && typeof prop === 'object')        target[key] = new Proxy(prop, handler);        return target[key];    },    set(target, key, value) {      console.log('Setting', target, `.${key} to equal`, value);        // todo : call callback        target[key] = value;      return true;    }  };    const test = {    string: "data",    number: 231321,    object: {      string: "data",      number: 32434    },    array: [      1, 2, 3, 4, 5    ],  };    const proxy = new Proxy(test, handler);    console.log(proxy);  console.log(proxy.string); // "data"    proxy.string = "Hello";    console.log(proxy.string); // "Hello"    console.log(proxy.object); // { "string": "data", "number": 32434 }    proxy.object.string = "World";    console.log(proxy.object.string); // "World"
like image 25
James Coyle Avatar answered Sep 19 '22 18:09

James Coyle


I published a library on GitHub that does this as well. It will also report to a callback function what modifications have taken place along with their full path.

Michal's answer is good, but it creates a new Proxy every time a nested object is accessed. Depending on your usage, that could lead to a very large memory overhead.

like image 44
Elliot B. Avatar answered Sep 22 '22 18:09

Elliot B.