I promised some people that I would talk a little about my feelings on ECMAScript proposals. I love javascript as a language. Sure, it has lots of warts, some that aren't easily dismissed. But it also has some really nice constructs that allow for elegant code solutions. My preference for javascript is purely subjective, and I don't mind admitting that. But being that I'm a staunch supporter of the language and the community, I'm also pretty opinionated about where it's going. These are just some of my concerns.
I should start by saying that I'm not against progress. Whenever I argue with people about javascript proposals, I always get the eventual argument that we have to move javascript forward and we can't be afraid of change. I want to go on the record as saying I want upgrades to javascript. But I don't think progress is a reason not to challenge ideas that I think are not fully formed or potentially problematic. This tension is good, because it keeps the standards makers on their toes. And it makes sure they get alternate input from people who have a different perspective on what makes a good language feature, but who are still invested in moving things forward.
Many ECMA proposals solve problems with the language, that's a given. And you can't really change a well-established language without creating other problems. That's unavoidable and shouldn't be a barrier to progress. My concern with some of the proposals is the impact of these other problems isn't always given enough weight in determining if the change is worth it, https://twitter.com/#!/polotek/status/187219527459811330.
I think the recent concensus on fat arrow syntax is a good example to illustrate this. I think it's a decent proposal. I'm not sure I agree that "fixing" dynamic function context with syntax is absolutely necessary. But after talking to several people, I seem to be in the minority, so I can accept that this is happening. It's also a fairly simple proposal on it's face. If you use the =>
syntax, you'll get a function. And that function will have a few other "nice" properties, like automatic binding to the closest lexical this
.
On the face of it, this seems like pure win. People want shorter function syntax and people want to worry less about this
. But this proposal has side effects, and more importantly it has affordances, that shouldn't be ignored. Most of these are expressed pretty well in this article by Angus Croll. In short, I'm concerned that people will use fat arrow, a lot, everywhere, and that's a problem.
Fat-arrow isn't just an alternative to normal function syntax. It's a new syntax that also introduces a completely new type of function. Functions that come from fat arrow have significantly different properties from normal functions. Some of the things you expect from normal functions are not applicable to fat arrow functions.
- Functions have dynamic
this
, fat functions always have athis
that you can't anticipate. - Functions can be dynamically dispatched with call/apply. Call/apply works with fat functions, but it will not change the context. Only pass arguments.
This is only a couple of items. There are several more differences that have to do with how the function body works. But these 2 have to do with functions that are passed around. These are differences that every developer who uses apis will have to deal with.
For one example, you if you take an object and mix it's methods onto your own object, you have to be aware of whether the functions are already bound. Otherwise you won't get expected behavior. Yes this is already a possibility with Function#bind
or closures, but it doesn't happen very often. It's not a common occurence. And this gets at the heart of my concern. I think it's very possible that fat arrow will become very common. Because as Angus points out, it will also be the shortest way to get a function. Programmers love short syntax. And they will jump on this. Unfortunately those same developers who don't get dynamic context, the ones we are trying to save, may not bother to be selective in when they use fat arrow functions vs normal ones. So we'll get proliferation of these things. And then it'll become a real problem for anyone who is used to taking advantage of the flexible power of javascript.
How big a problem is this? I don't know. It's certainly more of an unknown than the misunderstanding of dynamic this
. But from my long history with javascript, I think it's a potentially large issue. I think it's one of those things that gets away from you and eventually people are saying "you can't really trust call and apply, you don't know what kind of function you're getting". Or everyone's code is littered with some isBound type check and they continue to gripe about javascript's inconsistency.
But I could be way off base. This could be totally unfounded. Does anyone know how likely this type of thing is? How was it decided that the benefits of fat arrow outweight these potentially long-lasting detriments? Are there any plans to mitigate? These are the questions I'm left with once a "consensus" has been reached. I would love to have nothing better to do than pore over the es-discuss lists, but I just don't have the time. So I try to give my input on things as they gain enough popularity to get some publicity. And I don't always have constructive alternatives to present.
This is where I'm coming from when I scrutinize harmony proposals. Fat arrow isn't the only example; just the most recent. As an attempt to do more than just gripe, I think what would help is to publish concerns about the proposals and the rationale that minimizes those concerns. And even more helpful would be some talk about what criteria are concidered when evaluating proposals. When is battling current confusion more important than introducing new inconsistency? Why do we feel like the new weirdness will be less onerous?
I hope none of this feels like disparaging the work of standards body, and I hope it serves to clarify my views on progress. I don't know if I'll find more time to be a larger part of es-discuss and get in on these things earlier in the process. But I can promise not to be a person who just complains. Looking forward to feedback.
Hi Marco, thanks for your thoughts. Here's why I think your characterization of
this
isn't quite accurate.In JS today, all functions receive an implicit zeroth argument via method call, and you can explicitly pass the zeroth argument with apply and call. Now, in current JS, when you implement a function, you reference that zeroth argument with
this
. But you can also write a function that simply never refers tothis
at all. In such a case, passing the zeroth argument, whether via method call or via apply/call, will never have any effect on the function's behavior. This is already the case in JS today, with no fat arrows.From the perspective of a caller of the function, a client of the function, fat arrow does not change this at all. The only thing that's different about fat arrow is that the way you implement a function that ignores its zeroth argument actually repurposes the
this
keyword to refer to something else (namely, thethis
binding of the surrounding function). But that's purely a matter of how you implement the function -- it's an internal perspective.This is why I disagree when you say it's a "completely new type of function." From the perspective of a user of the function, it's no different from a function you can write today that simply does not refer to
this
. On the inside of that abstraction boundary -- i.e., from the perspective of the person who uses a fat arrow to implement a function -- it's simply providing convenient syntax for a common case, namely, when you want to write a function that ignores its zeroth parameter. On the outside of that abstraction boundary, there is nothing strange or uncommon about such a function.Dave