Arrow binding

David Herman dherman at mozilla.com
Mon Apr 23 15:36:49 PDT 2012


On Apr 23, 2012, at 3:53 AM, Alex Russell wrote:

> This means that most users of most functions can still use .call() and .apply() without apprehension. Functions are still "just functions".

You're assuming your conclusion: that there's some sort of platonic ideal ("just functions") of JS functions always having a use for their `this` binding. But when I pass function() { elt.style.background = 'yellow' } to setTimeout, is my function some betrayal of The JavaScript Way? No it's a function that changes the background color of an element. It's not evil. It's every bit as valid a function as one that's intended to be a method.

JavaScript uses functions for many different things: constructors, top-level functions, callbacks, and methods. Sometimes you need all their features, sometimes you don't.

> The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language.

I don't accept this frame. The contract of .call() and .apply() is that their first argument specifies the binding for `this`. The contract between a function and its caller is that the caller provides bindings for the arguments, and the callee decides what to do with those arguments. It is perfectly acceptable for the callee to disregard some arguments.

Now, it's certainly possible to make functions less abstract than necessary by using closed-over variables instead of arguments (including `this`). Maybe where I'm closer to agreement with you is that *when you're implementing methods* it's better to use `this` than to lexically close over the object the methods were created for. But not all functions in JavaScript are methods.

I'm much more sympathetic to the idea of having *two* shorter-function syntaxes, one optimized for methods and one optimized for non-method functions. I understand the concern about bloat, but to me it addresses the reality of different contexts in programming, e.g.:

    a.map(x => x + 1)

vs

    box = {
        _value: 0,
        get: () -> this._value,
        set(v) { this._value = v }
    }

> One option is to barrel onward with either unbound functions, hard bound functions, or some mix thereof. These are all painful in ways I don't need to spend time here explaining.

Maybe you do need to, because I'm not convinced. JavaScript already lets you do either. With the shorter function syntax, we've only been discussing conveniences for things you can already express. You claim that conveniences like fat arrow are "radical," but soft bind is the proposal that breaks an existing language guarantee. It introduces a new distinction: a callee can now change behavior depending on whether it was called via f() or vs f.call(null). That breaks the feature that you can always use .call/.apply as a drop-in replacement for the equivalent explicit call.

Dave



More information about the es-discuss mailing list