kofifus
kofifus

Reputation: 19285

javascript how to deep bind an object to a new 'this' value

I have a value which may be a primitive or a function or an object containing primitives/functions/objects recursively.

Given a theThis argument, how can I deep bind all functions which may be inside my value to theThis ?

I tried something like:

function deepBind(o, ths) { 
  Object.getOwnPropertyNames(o).forEach(key => { 
    const desc=Object.getOwnPropertyDescriptor(o, key);
    if (typeof desc === "function") Object.defineProperty(o, key, key.bind(ths)); 
    if (Object.getOwnPropertyNames(key).length>0) deepBind(o.key, ths);
  });
}

but that failed :(

I looked at some solutions like https://github.com/jonschlinkert/deep-bind/blob/master/index.js but that is not standalone.

I am looking for a deepBind(val, theThis) solution which is standalone. I need the solution to also cover getters and setters.

Thx!

Upvotes: 2

Views: 683

Answers (2)

adz5A
adz5A

Reputation: 2032

something along the lines of :

function deepBind (o, thisVal) {

   return Object.keys(o)
      .reduce((res, key) => {

          const v = o[key];
          const tv = typeof v;
          switch (tv) {
              case "object":
                  // should be updated for arrays...
                  if ( v !== null ) {
                      res[key] = deepBind(v, thisVal);
                  } else {
                      res[key] = v;
                  }
                  break;
              case "function":
                  res[key] = v.bind(thisVal);
                  break;
              default:
                  res[key] = v;
                  break;
          }
          return res;

      }, {});

}

It recursively copies values from the original objects, binding functions props to the thisVal.

Please note that binding recursively does not make a lot of sense because people expect the lexical context to be defined via its call site.

Upvotes: 1

Jaromanda X
Jaromanda X

Reputation: 1

This seems to work as you want

function deepBind(o, ths) {
    Object.entries(o).forEach(([key, value]) => {
        if (typeof value === "function") {
            // don't use value here :p
        	o[key] = o[key].bind(ths);
        }
        if (typeof value === 'object' || typeof value === 'function') {
        	deepBind(value, ths);
        }
    });
}
const v = {
    foo:3, 
    fn: function() {
        console.log(this);
    }, 
    obj: { 
        bar: 4,
        fn: function() {
            console.log(this);
        }
    }
};
var someThis = {hello: 'world'};
deepBind(v, someThis);
v.fn();
v.obj.fn();

Upvotes: 1

Related Questions