Shawn Erquhart
Shawn Erquhart

Reputation: 1858

How do adjacent parentheses in JavaScript functions work, and where is this documented?

Before you flag this as a duplicate, note: I understand what an IIFE is. This question is not about IIFE's.

The question: why is JavaScript able to parse adjacent parentheses, even in a standard function call? How does this construct - myFunction()() - work? For example, here's a bit of code from a test using Jasmine:

var element = compile('<div my-directive></div>')(scope);

Why would we go this route rather than passing the scope as the second argument? I don't believe this has anything to do with the keeping the global environment clean, and I can't find a thing about this particular construct anywhere, except where it concerns IIFE's. Is there a name for this construct?

Most importantly, please provide some sort of authoritative reference (link to mdn, ecmascript spec, etc).

Upvotes: 2

Views: 143

Answers (3)

StackSlave
StackSlave

Reputation: 10627

compile('<div my-directive></div>') must return a function which has a scope argument.

Maybe it would look something like this:

function compile(stringArg){
  return function(scopeArg){
    if(typeof scopeArg === 'object'){
      console.log(stringArg);
    }
  }
}

Upvotes: 1

EmptyArsenal
EmptyArsenal

Reputation: 7464

This has everything to do with closures. What's happening is that compile() must return a function that takes a variable, in this case scope.

Let's look at a simpler example:

function adder (first) {
  return function (second) {
    return first + second;
  };
};

adder(2)(3);
// returns 5

var add2 = adder(2);
// add2 now equals function (second) { return 2 + second; }

add2(4);
// returns 6

Often, a reason why you'd do this is because you want to reuse a function in a lot of ways. In the case of compile, you could run compile once, and reuse it with a number of different objects (or scopes). Also, you can make a number of variations with it.

i.e. The example above could be adder3, adder4, etc.

Compile probably has some behavior like this:

function compile(html) {
  // Some code here to turn string template into something more useable
  return function (scope) {
    // Scope being an object with values to plug into a template
    return DOM_element;
  }
}

Upvotes: 1

slebetman
slebetman

Reputation: 113876

This is the result of two rules:

  1. The return value of function calls may be used immediately (no need to assign to a variable).

  2. Functions are objects (they can be assigned to variables, passed as arguments and returned from function calls).

The first rule means that if you have code that does this:

function a () { return { hello : 'world' } }

You can do this:

a().hello; // returns 'world';

Which is basically the same as doing this without using any temporary variables:

var tmp = a();
tmp.hello; // value is 'world';

The second rule means that you can do this:

function b () { return function () { alert('hello world') } }
var c = b();
c(); // alerts 'hello world';

Combining rule 1 and rule 2 means the above can be rewritten as:

b()(); // alerts 'hello world';

Upvotes: 3

Related Questions