Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Old school C programmer needs JavaScript proxy demo #122

Open
scripting opened this issue Aug 2, 2019 · 6 comments

Comments

@scripting
Copy link
Owner

commented Aug 2, 2019

I'm an old school C programmer.
That's the syntax I've mastered for JavaScript.
I like callback hell. ;-)
I want to use proxies.
I need a C-like example app.

@tedchoward

This comment has been minimized.

Copy link

commented Aug 6, 2019

I’ve done a few things withProxy objects. I’ll look through my stuff and see if I can extract a good “hello world” for you.

@scripting

This comment has been minimized.

Copy link
Owner Author

commented Aug 6, 2019

Thanks Ted. That'll be helpful, I'm sure.

@tedchoward

This comment has been minimized.

Copy link

commented Aug 6, 2019

Ok, here's a really basic example. It creates a Proxy that writes to console.log every time you get or set a property of the object.

/**
 * Creates a `Proxy` that writes to `console.log` every time a property on the
 * object is accessed or set
 * @param {object} obj any JS Object
 */
function makeLoggerProxy(obj) {
  return new Proxy(obj, {
    /**
     * @param {any} target the object that this proxy wraps (obj)
     * @param {string|number|symbol} p the name of the property being accessed
     */
    get(target, p) {
      console.log(`${p} was accessed`);
      return target[p];
    },
    /**
     * @param {any} target the object that this proxy wraps (obj)
     * @param {string|number|symbol} p the name of the property being set
     * @param {any} value the new value of the property
     */
    set(target, p, value) {
      console.log(`setting ${p} = ${value}`);
      target[p] = value;
    }
  });
}

const myObj = {}; // create a new plain JS object

const myProxy = makeLoggerProxy(myObj); // create the wrapper proxy

myObj.firstName = 'Ted'; // logs nothing
const oldFirstName = myProxy.firstName; // logs 'firstName was accessed'

myProxy.firstName = 'Dave'; // logs 'setting firstName = Dave'
@tedchoward

This comment has been minimized.

Copy link

commented Aug 6, 2019

Here's a fantasy example:

// imagine if we had an odb-engine client
const odb = require('odb-engine');

// open a file from disk
const odbFile = odb.openFile('frontier.root');

// read value from a table
const notepad = odbFile.getValue('workspace.notepad');

// It would be neat, but not very elegant

// Now with proxies

const odbProxy = new Proxy(odbFile, {
  get(target, p) {
    return target.getValue(p);
  },

  set(target, p, value) {
    target.setValue(p, value);
  }
});

// much more elegant
const examples = odbProxy.examples;
examples.age = 37;
examples.flag = true;
@scripting

This comment has been minimized.

Copy link
Owner Author

commented Aug 7, 2019

@tedchoward -- first thanks for the examples.

I started with the first one, entered it into an app shell I have ready for these things, and here's the resulting app. It works as advertised.

What's confusing at first is the syntax of the second param to new Proxy (). It's an object, but the properties aren't named, or I don't understand what types they are.

Remember I'm an old school C programmer. This is not part of my vocabulary. :-)

What's going on??

@tedchoward

This comment has been minimized.

Copy link

commented Aug 8, 2019

The second parameter to new Proxy() is a Proxy handler. The documentation is here.

The Proxy handler is where the "magic" happens. All the properties of the handler are optional. In my example, I only defined get and set. It basically allows you to write functions that intercept pretty much any interaction that is possible to have with an object.

I could have written the example like this:

function makeLoggerProxy(obj) {
  const handler = {};

  handler.get = function (target, p) {
    console.log(`${p} was accessed`);
    return target[p];
  };

  handler.set = function (target, p, value) {
    console.log(`setting ${p} = ${value}`);
      target[p] = value;
  };

  return new Proxy(obj, handler);
}

I don't know if that makes it easier or harder to see what's going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.