Kaustav Kaustav - 4 months ago 15
Javascript Question

Javascript IIFE as an object's property (method)

I'm trying to use an IIFE as a method (which might be wrong).

Why ? Because, I'm trying to implement the proxy design pattern.

In adobe extendscript, there is an "app" object to access documents, etc, like -

var length = app.activeDocument.length; // or some other property


Now, I wanted to put a proxy around "app". So I created a proxy object -

var AppProxy = {
activeDocument: function() { // do stuff...; return app.ActiveDocument; }
}


But now, this is how I had to access it -

var length = AppProxy.activeDocument().length;


But this is how I want to access it -

var length = AppProxy.activeDocument.length; // no parenthesis


So I read about IIFE, and ended up doing this -

var AppProxy = {
activeDocument: (function() {
// do stuff...;
return app.ActiveDocument; })()
}


And as expected, the AppProxy.activeDocument gets called automatically when AppProxy is defined, i.e. even BEFORE it reaches var length = AppProxy.activeDocument.length.

So how do I prevent this from happening when AppProxy is defined as an object literal ?
Is there a workaround to my requirement ?

Thanks.

Answer

But this is how I want to access it -

var length = AppProxy.activeDocument.length; // no parenthesis

To do that, you need to define activeDocument as a property with a getter function. This is possible in browsers with proper support for ES5's getters and setters, which is all modern browsers (not IE8 and earlier). (Before ES5, there was a never-standardized syntax for this that some browsers supported, but again not IE8 or earlier).

In ES5, you can do this either with Object.defineProperty or by defining a getter in an object initializer. Here's Object.defineProperty:

// ES5+ only
var AppProxy = {};
Object.defineProperty(AppProxy, "activeDocument", {
    get: function() {
        // do stuff...;
        return app.ActiveDocument;
    }
});

Here's doing it as part of the object initializer:

// ES5+ only
var AppProxy = {
    get activeDocument() {
        // do stuff...;
        return app.ActiveDocument;
    }
};

Having done either of those, then this:

var length = AppProxy.activeDocument.length;

...runs that function, even though it doesn't look like it does. The function call still happens, it's just hidden.

But if you need to support obsolete browsers (even here in mid 2016, IE8 still has ~5% market share) or if you don't want to hide the fact you're calling a function, just call the function:

var length = AppProxy.activeDocument().length;