When I first read that javascript was getting a arrow function shortcut, I was happy. Like this kind of happy:

Seriously. So happy. Check out the code below and tell me it doesn’t feel great.

1
2
3
4
5
var times_2 = [1,2,3,4].map((num) => num * 2);

times_2.forEach((num) => {
console.log(num);
});

Pretty, great, right? The arrow function shortcut seemed like a perfect port of the lambda syntax from C#. Buuuut it’s not. Like, not at all.

When you use the ES6 arrow function, it creates a lexical scope. Lexical (also called static) scoped functions are functions where the this context is set to it’s parent, and cannot be altered. This means that the examples above would translate (roughly) to this JavaScript:

1
2
3
4
5
6
7
var times_2 = [1,2,3,4].map(function(num) {
return num * 2
}.bind(this));

times_2.forEach(function(num) {
console.log(num);
}.bind(this));

Now in these two examples the scoping isn’t an issue. In fact in a lot of cases you won’t care about the => operator creating a static scope. But it’s really easy to forget, especially when everyone on the internet just refers to this thing as the “ES6 arrow function”.

For real? “Arrow function” makes it sound like this isn’t doing anything other than dropping a function into my code. It’s a bad name and it should feel bad.

To me, the better name for this is the “static scope operator”. Yeah it’s longer, fite me. Authors Note: don’t really fight me, I’m overly squishy and bruise easily. Let’s grab a drink of your preference and talk about movies or comics instead.

Using a name that doesn’t call out that this operator creates a static scope seems like a bad idea to me. Scope is an incredibly tricky thing to understand in JavaScript, so to me it should be very obvious when we are about to muck around with it.

This obfuscation of the static scope operators intent often leads to code that is harder to understand. For example, what if we wanted to create an action handler for a React component?

1
2
3
4
5
6
7
8
9
class MyComponent extends React.Component {
onLinkClick = () => {
// do stuff
}

render() {
return <a onClick={this.onLinkClick}>Clicky</a>;
}
}

The low number of lines of code here is a plus, but that onLinkClick property is hard to grok at first glance. When we write code, we’re writing code for the people that we work with now and in the future who will maintain our code. Code is for coworkers.

Let’s try cleaning this up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import _ from 'lodash';

class MyComponent extends React.Component {
constructor() {
_.bindAll(this, 'onLinkClick');
}

onLinkClick() {
// do stuff
}

render() {
return <a onClick={this.onLinkClick}>Clicky</a>;
}
}

To me this second example is much easier to read and is clearer about how the code functions. The scope binding is clear, and explicit.

So when do I use a static scope operator? Usually in simple callbacks, like map/reduce or a one line promise handler. I don’t see the value of using => for every function by default, especially not in the class definition like above. But if you disagree, cool. I’d love to hear your points so post a comment, twit me on twitter (@codeimpossible), or chat with me at a conference.

My intention here wasn’t to make you feel bad for using static scope operators (yep, I’m going to keep calling it that). I do hope that this post made you think more about the abstractions you use and make you ask yourself if they making your code easier to read, maintain, and test, or if they are just saving you a few keystrokes.

Comment and share

Ever been working on a customer’s site, writing some really awesome jQuery, you deploy it, and everything is awesome. And then you get an email one day…

Has this ever happened to you: you’ve been working on a customer’s site, writing some really awesome jQuery flashy, fadey, scrolly, interactivey thing, you deploy it, and everything is awesome. The customer rejoices and the customer’s customers rejoice. Rejoicing is had by everyone. And then you get an email one day:

“Everything is broken. We’ve kidnapped your dog. Fix our site or you’ll never see Spartacus again.”

And before you have time to wonder why you ever named your dog “Spartacus” to begin with (i mean come. on.), you’re off in debug hell.

You load the site and see all sorts of weird errors: "$().ready is not a function" "$(document) doesn't support this property or method" Or my personal favorite: "null is null or not an object"

You open up FireFox, activate FireBug, load the console, and type alert($), press run, and instead of seeing the expected jQuery function:

1
2
3
function (E, F) {
return new (o.fn.init)(E, F);
}

You instead get:

1
2
3
4
5
6
7
8
9
10
11
12
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++) {
elements.push($(arguments[i]));
}
return elements;
}
if (Object.isString(element)) {
element = document.getElementById(element);
}
return Element.extend(element);
}

Or even:

1
2
3
function $(id) {
return document.getElementById(id);
}

DOH! Looks like another javascript library has been loaded and has overwritten the $() shortcut for jQuery. Woe is I. Why can’t we all just get along?!? Well, we can’t stop people from including their favorite javascript libraries, but what we can do is prevent our code from suffering as a result. We’ll need a nice, big beefy, bodyguard to make sure our code isn’t messed with while it’s out clubbing with Prototype, Scriptaculous or even MooTools (who invited him??!?). Here’s what our bodyguard function will look like

1
2
3
( function($) {

} ) ( jQuery );

So what this does is call our anonymous function and pass the jQuery object. This will scope $ our little function so we won’t step on anyone else’s toes (and they won’t bump into us while we’re on the dance floor and spill our drink everywhere). Okay, I think I've taken the clubbing metaphor far enough.

Basically this will allow our code to run and use the $ shortcut for JQuery as if it were loaded without any of these other libraries on the page. Here is what the completed code would look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript">
</script>


<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js" type="text/javascript">
</script>

<script src="http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.3/scriptaculous.js" type="text/javascript">
</script>


<script type="text/javascript">
( function($) {
// we can now rely on $ within the safety of our "bodyguard" function
$(document).ready( function() { alert("nyah nyah! I'm able to use '$'!!!!"); } );
} ) ( jQuery );

//this will fail
$(document).ready( function() { alert('fail?'); } );
</script>

I love using this simple self-calling anonymous function style when working with jQuery because it saves me from typing jQuery(), which really does look a lot more ugly than using the $() shortcut. It also protects my code from any scoping issues and lets the code function normally when jQuery is put into no conflict mode.

My opinion, if you’re doing work in jQuery on sites that you don’t control 100%, you should be using this method to protect your code and your clients.

Updated: changed link for jquery to use 1.4.1 at the google CDN (tsk, tsk, tsk I was using the googlecode.com link)

Comment and share

  • page 1 of 1

Jared Barboza

dev @Hudl. I like javascript, cats and video games. I’m an adult, opinions here are mine.


Software Developer, npm installer


Austin, Texas