Non-method functions and this

Brendan Eich brendan at mozilla.com
Sun May 15 14:54:04 PDT 2011


On May 15, 2011, at 2:36 PM, Axel Rauschmayer wrote:

> Caveat: I am aware that what I’m suggesting might clash too hardly with current semantics (how to handle invocation, apply(), call(), etc.), but I am interested in the arguments against it.

The strawman contains bits of rationale, please look for them.


>>> (1) I would prefer non-method functions not to have a binding for |this| at all.
>> 
>> How do you define "non-method"?
> 
> A function that is not invoked as method. Right now, the same kind of construct is used for both true functions and methods. I’m proposing a new construct (similar to the distinction that Python makes): a function that does not have an implicit |this| parameter.
> 
>> It would make an early error for many functions written today as function declarations, which use |this| because they are assigned as property values (i.e. as methods), to call the |this| usage in such functions an early error. That would be a harsh migration tax, even though compile-time. We are not changing Harmony that much.
> 
> Right. It could be introduced via the arrow function syntax, with the "function" operator remaining as is:
> 
> var obj = {
>    id: "123",
>    method: (x) => {  // same as function operator
>        [1,2].forEach((i) -> {  // new construct
>            console.log(this.id + ": " + i + " - " + x);
>        });
>    }
> }

The goal of http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax and the earlier, somewhat abandoned (outside of Traceur) http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax, is to make "just syntax" at the minimum. Not new kinds of functions, one that has no |this| parameter.


> Thus:
> => and function: |this| is an implicit argument (“methods”)
> ->: |this| is not an implicit argument; currently simulated via binding (“functions”)
> 
> The arrows are swapped compared to the strawman, because => is more “heavy-weight” here.

How is implicit (let's please say "dynamic") |this| more heavy-weight? It's what is in JS today, optimized heavily in current VMs, not requiring a cloned function object to bind a particular |this| to the function value.

In contrast, binding |this| has noticeable cost even for JS hackers, if overused. It is the exception, by static source function call vs. bind counting anyway.

The CoffeeScript decision to use fat-arrow to connote the higher cost of bind (or the closure-based equivalent used by the CoffeeScript compiler) puts the fat-arrow on the heavy-weight target, ITSM.


> 
>>> Isn’t (1) a better solution?
>> 
>> Why?
> 
> It is easier to understand for beginners. |this| always being an implicit parameter trips up many newbies. I also find it a cleaner way of getting lexical |this|.

As you seemed to grant, we are not changing anything to do with |this| for function declarations and expressions spelled using 'function'. Making arrow functions differ subtly is a learning burden too. (So is deviating from CoffeeScript, FWIW.)

/be


More information about the es-discuss mailing list