JavaScript language extensions with function calls lacking parenthesis - are they possible?

114 Views Asked by At

Is it possible, by any means, to do something like this:

function A() {
    var Loaded = 'loaded';
    raise Loaded;
}
function A_raise(evt) {
    console.log(evt);
}
A.prototype.constructor = A;
A.prototype.raise = A_raise;

The critical part being the line:

raise Loaded;
2

There are 2 best solutions below

7
On

The only way to get a parentheses-less function call in JavaScript is to define a setter/getter property, or to override one of the special methods : toString or valueOf. In neither case do you have really good control over the parameter that gets passed to the call.

function C() {}
C.prototype.valueOf = function () { alert("valueOf called"); };
var c = new C();
// No parentheses
+c;

You can invoke a constructor without parentheses, but again, cannot pass arguments.

function f() { alert("f"); }
// No parentheses
new f

One reason you can't is semicolon insertion.

f()

is a function call, as is

f
()

and

if
(x) { }

is a valid conditional because if is a core part of the language but if you could just drop the parentheses from a function call then semicolon-insertion would have to treat code like

var x = raise

y

as a variable initialized to the result of calling a function.


Since you asked about language extensions, Chapter 16 of the EcmaScript specification says that interpreters are allowed to add to the grammar of the language,

An implementation may extend program syntax and regular expression pattern or flag syntax. To permit this, all operations (such as calling eval, using a regular expression literal, or using the Function or RegExp constructor) that are allowed to throw SyntaxError are permitted to exhibit implementation-defined behaviour instead of throwing SyntaxError when they encounter an implementation-defined extension to the program syntax or regular expression pattern or flag syntax.

so since

 raise foo

is not a valid expression or statement in the language, they could allow it, but they could not do so in a way that changes the meaning of

 raise
 foo

which must have the same meaning as

 raise;
 foo

so the interpreter would have to make raise a new restricted production which is problematic because of the verbiage:

The following are the only restricted productions in the grammar:

That is probably meant to be non-normative, but it is not explicitly so.

2
On

You can't define new statements in JavaScript, so you can't actually create the syntax you show in A.

Edit: From your comment on the question, it's clear you're looking to define a new statement/keyword. No, you can't do that.


Original answer:

Is your goal inside the A constructor to call the A_raise function? If so, you're really close. Just change:

raise Loaded;

to

this.raise(Loaded);

Live Example | Source

Within the call to a constructor function via the new keyword, this is the newly-constructed object, which has already received its prototype from the constructor function's prototype property. So this will have raise on it (via its prototype), and raise will refer to the A_raise function.

But again, you need the parens (and the this.).