Search code examples
javascriptmethodsprototypefallbackspl-autoload-register

Javascript, Object prototype - avoid writing full path


I know my title may not be very clear, I'll try my best to explain what I'm trying to achieve.

I know that modifying prototypes is generally frowned upon, and for good reason, so I'm trying to figure out a way to do so without adding any more than one item to the prototype.

I know that I could simply do something along the lines of

Object.prototype.collection = {};
Object.prototype.collection.method1 = function(){ . . . };
Object.prototype.collection.method2 = function(){ . . . };
Object.prototype.collection.method3 = function(){ . . . };
etc.

And then whenever I wanted to use one of the methods I could call

objectInstance.collection.method1();

The problem with this is that eventually it can get pretty wordy and tedious, not to mention if you're calling a hundred methods from this collection, the word 'collection' a hundred times is redundant and a waste of bytes.

So I was hoping for a technique of creating methods in this manner, without having to write the full path every time. i.e. I could write

objectInstance.method1();

And it would know right where to look.

My thought process at this point is that obviously calling the latter would throw a method does not exist error. But I'm curious if there is any manner of intercepting this error?

For instance, in PHP there is the spl_autoload_register() function, which is called whenever a class has not been defined, allowing you to do whatever is necessary to load/define it. Is there any equivalent strategy for this circumstance?

Maybe I could add a secondary 'fallback' method, like so:

Object.prototype.fallback = function( undefinedMethod ){

    if(this.collection.undefinedMethod){

        this.collection.undefinedMethod();

    }
};

And just have this called every time a method is undefined, passing in the method.

Any help for anything along these lines, or if it's even possible, would be greatly appreciated.


Solution

  • One of possible approaches is to use the newly introduced Proxy that allows you to intercept arbitrary calls to object members.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

    An example from the MDN

    var handler = {
      get: function(target, name){
        return name in target?
            target[name] :
            37;
      }
    };
    
    var p = new Proxy({}, handler);
    p.a = 1;
    p.b = undefined;
    
    console.log(p.a, p.b); // 1, undefined
    console.log('c' in p, p.c); // false, 37