-1

I'm writing an API and I need to execute a ternary inside a "getter" function for various fields. This works fine but I don't want the end user to have to use parentheses when accessing these fields.

Strangely the getter code actually executes when I access the field without the parentheses but I'm wondering if this is normal for javascript or if this is browser dependent? Currently using Firefox 31.

This works:
var theScript = Scripts.jQuery_1_11_1_js(); // Note I'm using the parentheses

This also works even without parentheses. How?:
var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses

Example API:

var Scripts = (function () {
    function Scripts() {
    }
    Scripts.isProduction = false;
    Scripts.Url = "/Scripts";
    Scripts.jQuery_1_11_1_js = function () {
        return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
    }
    return Scripts;
})();
var theScript = Scripts.jQuery_1_11_1_js();
var theScript = Scripts.jQuery_1_11_1_js; /// why does this work?
user2864740
  • 60,010
  • 15
  • 145
  • 220
TugboatCaptain
  • 4,150
  • 3
  • 47
  • 79
  • `var theScript = Scripts.jQuery_1_11_1_js;` makes `theScript` hold the function. Using which, you can call `console.log(theScript());` later. In the `var theScript = Scripts.jQuery_1_11_1_js();`, the variable `theScript` holds the string, which is the result of the function. – shahkalpesh Aug 02 '14 at 07:49
  • 5
    They don't do the same thing. Try `console.log(theScript)` after each of them and you'll see the difference. – Barmar Aug 02 '14 at 07:50
  • How are you testing whether or not it "works"? With your code, that shouldn't call the function. – Qantas 94 Heavy Aug 02 '14 at 07:50
  • http://jsbin.com/wuzimere/1/edit?html,output (aka What Barmar said). – Quentin Aug 02 '14 at 07:50
  • 1
    When you don't have the parentheses, you're not calling the function, you're just returning the function itself. – Barmar Aug 02 '14 at 07:50
  • http://stackoverflow.com/questions/21568499/invoke-a-function-without-parentheses-javascript?rq=1 – user2864740 Aug 02 '14 at 08:01
  • Doh, had some left over code elsewhere that made it look like it was working but in fact it's just returns the function object itself. – TugboatCaptain Aug 02 '14 at 08:06

1 Answers1

4

This also works even without parentheses. How?:

var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses

No, it doesn't. The line executes just fine, but it doesn't call Scripts.jQuery_1_11_1_js, it just sets the value of theScript to a reference to the function Scripts.jQuery_1_11_1_js.

There are only two four (as of ES2015) ways I know of to call a function without parentheses:

  1. Define the property on Scripts as an ES5 getter. Here's the ES5 syntax for doing that:

    Object.defineProperty(Scripts, "jQuery_1_11_1_js", {
        get: function() {
            return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
        }
    });
    

    Now, the line

    var theScript = Scripts.jQuery_1_11_1_js;
    

    ...will call that anonymous function we defined as the getter for the property.

    Unfortunately, you can't do that in IE8. In IE8 (bizarrely), Object.defineProperty can only create properties on DOM elements, not normal objects. IE9 supports it properly.

  2. Just for completeness, there is a second way, with new:

    var foo = new Foo;
    

    ...which is equivalent to

    var foo = new Foo();
    

    But of course, you don't want to do that unless Foo is meant to be a constructor function, as it creates an object to pass to Foo as this.

  3. Calling a tag function:

    someFunction`template contents here`;
    

    That doesn't look like a function call, but it is. It parses the template, evalutes any token expressions, and passes the raw form of the template (an array of strings with an added raw property, subsequent arguments for the token substitutions) into someFunction. Whereas someFunction(`template contents here`) would evaluate the template, evaluate any token expressions, and substitute them into the template producing a string, and then pass the string into someFunction. More on MDN.

  4. Do just about anything on a Proxy object, since all the fundamental object operations (getting properties, setting properties, defining properties, getting its prototype, etc., etc.) can be trapped on proxies, generating a call to a trap handler.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875