26

There are things like

f.call(...)
f.apply(...)

But then there's this

(1, alert)('Zomg what is this????!!!11')

"1" does not seem to mean much in this context, the following works just fine:

(null, alert)('Zomg what is this????!!!11')
(1, null, alert)('Zomg what is this????!!!11')
(undefined, alert)('Zomg what is this????!!!11')

Could you point to a specific part of ECMAScript which describes that syntax?

genesis
  • 48,512
  • 18
  • 91
  • 118
Art
  • 21,071
  • 27
  • 83
  • 97
  • 1
    Related: [Does the comma operator influence the execution context in Javascript?](https://stackoverflow.com/questions/36076794/does-the-comma-operator-influence-the-execution-context-in-javascript/36077031#36077031) – try-catch-finally Jul 22 '17 at 07:44

3 Answers3

53

You are just using The Comma Operator.

This operator only evaluates its operands from left to right, and returns the value from the second one, for example:

(0, 1); // 1
('foo', 'bar'); // 'bar'

In the context of calling a function, the evaluation of the operand will simply get a value, not a reference, this causes that the this value inside the invoked function point to the global object (or it will be undefined in the new ECMAScript 5 Strict Mode).

For example:

var foo = 'global.foo';

var obj = {
  foo: 'obj.foo',
  method: function () {
    return this.foo;
  }
};

obj.method();      // "obj.foo"
(1, obj.method)(); // "global.foo"

As you can see, the first call, which is a direct call, the this value inside the method will properly refer to obj (returning "obj.foo"), the second call, the evaluation made by the comma operator will make the this value to point to the global object (yielding "global.foo").

That pattern has been getting quite popular these days, to make indirect calls to eval, this can be useful under ES5 strict mode, to get a reference to the global object, for example, (imagine you are in a non-browser environment, window is not available):

(function () {
  "use strict";
  var global = (function () { return this || (1,eval)("this"); })();
})();

In the above code, the inner anonymous function will execute within a strict mode code unit, that will result on having the this value as undefined.

The || operator will now take the second operand, the eval call, which is an indirect call, and it will evaluate the code on the global lexical and variable environment.

But personally, in this case, under strict mode I prefer using the Function constructor to get the global object:

(function () {
  "use strict";
  var global = Function('return this')();
})();

Functions that are created with the Function constructor are strict only if they start with a Use Strict Directive, they don't "inherit" the strictness of the current context as Function Declarations or Function Expressions do.

Christian C. Salvadó
  • 723,813
  • 173
  • 899
  • 828
  • Thanks for the ECMAScript link – Art Mar 01 '11 at 23:16
  • 1
    Regarding: "will simply get a value, not a reference". That's not what's happening at all. You're seeing different behavior because you're invoking the function without the [dot operator](https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators). You'd see the same behavior if you did this: `var temp = obj.method; temp();` – Wayne Mar 01 '11 at 23:28
  • @lwburk: I'm talking in terms of the specification, it will get a *value*, not a [Reference](http://es5.github.com/#x8.7), see what the comma operator returns: "Step 4. Return GetValue(rref)." It uses the [`GetValue`](http://es5.github.com/#x8.7.1) abstract operation. The example you post is indeed equivalent, but slightly different, in that case `temp` is a *reference* with no *base object*. – Christian C. Salvadó Mar 01 '11 at 23:33
  • @lwburk, Ah, also, you can see that your example isn't *exactly* equivalent, in ES5: `eval('foo')` is a [Direct Call to eval](http://es5.github.com/#x15.1.2.1.1), but `(1, eval)('foo')` is not, this case has not to do with the `.` property accessor. Kangax explains this very well [here](http://perfectionkills.com/global-eval-what-are-the-options/#indirect_eval_call_theory). – Christian C. Salvadó Mar 01 '11 at 23:50
  • Very interesting. My point was far more pedestrian: `(1, obj.method) === obj.method // true` – Wayne Mar 02 '11 at 00:01
  • Analogous `(1, obj.method)();` will be something like `var tmp = obj.method; tmp();` which uses `this === window` in non-strict mode or `this === undefined` in strict mode. – Caramiriel Oct 19 '16 at 08:58
9

It's the comma operator, which evaluates both of its operands and returns the value of the second one.

So, something like (null, alert) evaluates to the alert function, which you can immediately call using parentheses.

It's described in section 11.14 of ECMA-262 (PDF).

Wayne
  • 56,476
  • 13
  • 125
  • 118
3

The comma operator causes expressions to be evaluated sequentially. Wrapping the expressions in parentheses returns the value of the last expression. So (1, alert)("hello") is functionally equivalent to:

1;
alert("hello");

Off the top of my head, I can't think of a reason to do this.

gilly3
  • 78,870
  • 23
  • 132
  • 169