0

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;
CoryG
  • 2,429
  • 3
  • 25
  • 60
  • If it's a critical part, perhaps you could tell us what you mean by `raise` (as that's not a JavaScript keyword). Did you mean `throw`? If not, what *do* you mean? – T.J. Crowder Feb 27 '13 at 18:00
  • If you don't like the _messy_ JavaScript syntax you could look at languages that compile to JavaScript like CoffeeScript. – Halcyon Feb 27 '13 at 18:01
  • It was just an example, the goal would be to create a new keyword named "raise" that passes a parameter to A_raise. – CoryG Feb 27 '13 at 18:06

2 Answers2

4

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.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • I realize trying to add a new keyword to a scripting language is a bit to ask, so I don't mind a hack of a way to do it, but with properties aren't you limited to using an equal sign? I'd really like to avoid using parenthesis or any symbols - the goal is "raise Loading;" – CoryG Feb 27 '13 at 18:10
  • @CoryG: Not with the current JavaScript, no. A property getter *almost* works (you don't need an `=`), but you can't pass an argument into it (and it would have to be `this.raise Loading;` at which point, really, you may as well throw parens at it). – T.J. Crowder Feb 27 '13 at 18:35
  • How do you reduce it to "this.raise Loading"? I've been able to get it down to "raise(Loading);" or "raise = Loading;" but nothing but a space between "raise" and "Loading" is where I have issues. – CoryG Feb 27 '13 at 19:21
  • @CoryG, there's no way. The phrase `raise Loading` is simply not a valid JS expression, so it won't make it past the parser. – Mike Samuel Feb 27 '13 at 19:30
  • I'm inquiring to the "this.raise Loading;" that T.J. Crowder cited in his comment. – CoryG Feb 27 '13 at 19:35
  • @CoryG, `this.raise Loading;` is also not a valid expression. Please see my edit re language extensions. – Mike Samuel Feb 27 '13 at 20:00
  • @CoryG, you might be able to get `Loading in this.raise` to do what you want by abusing [proxies](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Proxy) but I think that automatically coerces the argument to a string. – Mike Samuel Feb 27 '13 at 20:04
1

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.).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Sorry, I probably left too much of the detail in the title of the post - the goal is to create a new keyword named "raise" that avoids the need to use "this." or parenthesis. – CoryG Feb 27 '13 at 18:07
  • @CoryG: Yeah, just saw the comment on the question and updated. I'm afraid you can't do that, no. – T.J. Crowder Feb 27 '13 at 18:08