Hoist The Jolly Roger

I recently stumbled across this article from David Shariff while I was looking for JavaScript exercises for my students at Bloc. His article details topics across the entire front end that are extremely important, but what caught my eye in particular were the JavaScript concepts. In my continuous quest for JavaScript World Domination™ I thought this list was a great representation of "topics that I sort of understand, but that have to Google when I'm pressed for details" on, so I'm going to work through these concepts one by one to solidify my understanding.

Is Hoisting Foisting You?

Today I'm going to look at Hoisting. What I'm going to do is distill my own understanding of this topic into some useful examples that hopefully will make the topic clear. The worst case scenario is this only helps me, but maybe you'll find some benefit from these examples as well.

My goto for any grainy, tough JS subject is going to be first and foremost Kyle Simpson because his You Don't Know JS series does such a great job thoroughly breaking down these topics. Here are the selections that give the best background for what I'm going to discuss below:

What I like to do when I'm bulking up on a topic is to go through his chapter on the relevant subject matter, then recreate all of his (very dry) examples with something that resonates more with me.[1] I definitely recommend this approach for everyone. It's a great way to start to own the material and to get your dang fingers on the keyboard.

If you find that you enjoy Kyle's style and approach, you might consider picking up the whole series.
(I'm trying out the Amazon Affiliate program, so if you purchase the book from that link, I'll get something like 80 cents!)

Hoisted By My Own Petard

This topic is dear to my heart because it sent me into a near existential crisis when I first learned about it. What do you mean the JS engine just moves my code after I've written it? past-Alex asked, incredulous at the thought of things happening underneath the surface. JavaScript moves my code around while it runs?!

No.

Well, not in the way that the term hoisting suggests. But it is a useful way to think about this behavior. You'll see the phrase "hoistable" pop up a lot if you go read the ECMA specs for JavaScript[2], so even the internal team finds the metaphor useful. But what actually happens is a little more nuanced. It warrants a whole post in of itself (see some of the Additional Reading below), but a sufficient summary might be: JavaScript pulls declarations, but not initializations into memory before executing a block of code

When we talk about hoisting, we can talk about Variable hoisting and Function Hoisting. They behave pretty similarly, but there are a few distinctions to keep in mind, and so let's talk about them separately. Crack open your favorite REPL environment and let's dive in.

Variable Hoisting

The first thing to keep in mind when we talk about hoisting is declaration versus initialization. Typically, you see these steps combined:

1
var dog = 'Fido';

In the line above, we both declare (var dog) and initialize (dog = 'Fido') the variable dog. We don't usually think of these are separate steps, but from the perspective of the JS compiler, they are indeed distinct.

Case in point, what logs to the console here?

1
2
console.log(dog);
var dog = 'Fido';

What about in this essentially identical question, presented with a little bit more of a cheeky setup?

1
2
3
4
5
6
7
8
9
function bar() {
var baz = 10;
console.log(foo);
var foo = baz;
}

var foo = 11;

bar();

In both examples, the same principles are at play.

Hulk Smash

If you run the above code, you'll find that it returns undefined in both cases. This is where we use the "hoisting" metaphor to explain this behavior. Imagine that JavaScript literally pulls apart your variable assignments and then hoists the declarations up to the top of the scope that they are introduced in.

I like to imagine The Incredible Hulk leaping onto the scene, grabbing hold of your delicate variable, and rending it in two, tossing one half, the declaration, high up onto a building (the top of the block of scope you are in), before bounding off in search of other variables to harass.

The first examples becomes:

1
2
3
var dog;
console.log(dog);
dog = 'Fido';

If you think back to how variables behave in JS, you might remember that any declared but unassigned variable is assigned the data type undefined until it is initialized.

Try the same exercise with my second example. You should come up with the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

var foo;

function bar() {
var baz;
var foo;
baz = 10;
console.log(foo);
foo = baz;
}

foo = 11;

bar();

Notice that our hoisted variable declarations are brought to the top of their respective scopes.

Function Hoisting

Above, we covered the fact that variable declarations are "hoisted" to the top of their scope, but what about functions? At a glance, it seems like functions don't follow this rule of "process the declaration before the initialization."

Put another way, why does this work?

1
2
3
4
5
proclaimThisFact("Pizza should not have eggs on it");

function proclaimThisFact(fact) {
console.log(`${fact}!`);
}

Shouldn't we get an error of some sort? Maybe something telling us that proclaimThisFact is not a function? Why can we use this function before it is defined?

Remember that there are several ways to define a function in JavaScript. One way, used above, is called a function declaration. Alternatively, we could have written our function like this:

1
2
3
4
5
proclaimThisFact("Pizza should not have eggs on it");

var proclaimThisFact = function (fact) {
console.log(`${fact}!`);
}

This is called a function expression. Armed with your refined knowledge of how variable declarations behave, what do you think the difference is in behavior if you run my second example, modified to use a function expression?

It blows up! Just like we expected the first example to. And pay close attention to the error you get here. It's a TypeError, not a ReferenceError like you might expect. (To see the difference, try to call a function that doesn't exist at all: defamePasta("linguini")).

The error comes from the fact that we are asking our variable to be a function before it has been initialized as one:

1
2
3
4
5
6
7
var proclaimThisFact; // proclaimThisFact is undefined
proclaimThisFact("Pizza should not have eggs on it"); // JS Engine: "lol wut is this thing"
// TypeError!

proclaimThisFact = function (fact) {
console.log(`${fact}!`);
}

ES6's let and const

let and const are ES6 compliments to the original JavaScript syntax. They are interesting, helpful additions to the language for a variety of reasons, but for the purposes of our discussion of hoisting, we'll just talk about one specific behavior, which is:

let and const are not hoisted

When a variable is declared using either const or let, it is not hoisted in the way that we see above with var. Instead, its point of declaration is treated "in-line." Essentially, it behaves closer to the way it looks in the written code.

Take my original example, but we replace var with const:

1
2
console.log(dog);
const dog = 'Fido';

Bam! We get hit with a reference error! And I argue, this is preferable to what we see as a result of hoisting + var. It's much better to trigger an error like this in development than to chase down strange bugs that are caused as a side effect of your variables sneaking around with undefined values. For that reason, I take the approach of always using const[3] for my variables, rather than var. I haven't found any compelling reasons to use var when const/let are available to me.[4]

A best practice that Kyle Simpson suggests in the above mentioned sources is to declare all of the variables you will be using at the tops of their relevant scopes:

1
2
3
4
5
6
7
8
9
bar();

function bar() {
let foo;
const baz = 10;

foo = baz;
console.log(foo);
}

Key Takeaways

  • Just use let and const to avoid this nonsense
  • Only declarations are hoisted, not initializations
  • Function declarations (function lookAtThisPizza() { ... }) are fully hoisted
  • In function expressions (var lookAtThisPizza = function () { ... }), only the variable is hoisted

While ES6's const and let allow us a comfortable way to side step this issue by simply declaring our variables at the tops of our scopes and carrying on like civilized people, it is important to understand var's hoisting behavior. For one, JavaScript is the most ubiquitous language in use on the web and there are millions of lines of code running in production today that were created pre-ES6. You may one day have to maintain or refactor some of that code, and knowing why it behaves the way it does will be helpful.

Furthermore, let and const don't have complete browser support, so if you're forced to continue support for IE10 or something similar, you may need to hoist yourself up by your own bootstraps and navigate this quirk of the JavaScript language.

Additional Reading

Footnotes


  1. Generally, food based examples decrying improper pizza toppings or other less worthy snack foods.

  2. You know, for fun.

  3. I try to default to const and then change to let only when necessary.

  4. Outside of writing examples for people running into this problem, of course.

Civic Engagement With React

I built You Work For Me as part of the last quarter of my bloc.io program. The curriculum covers the Ruby/Rails and JavaScript/AngularJs stacks, but, having not had a great time with AngularJs, I was interested in exploring something new. My mentor suggested I try React.

The Initial Idea

This time coincided with the Fall 2016 elections in the US, and I felt motivated to create something to encourage people to engage more in our political processes. I decided to build something that makes it easier to contact your congressional representatives. Below, I describe in more detail what my site, named You Work For Me, does and how I put it together. I finish with some ideas about the direction I’d like to take future development. The basic form of the app is as follows: a user navigates to the site and is presented with the contact information of their three congressional representatives. While simple, this foundation was easy to understand so that I was able to focus on learning React as well, and contains a basic set of features that I can augment in the future. The way YWFM gets and presents the congressional data is relatively straightforward. First, it takes the latitude and longitude of the user from the geolocation object in the browser, then sends an API request to the Sunlight Foundation’s Congress API, and finally, displays that data in a useful format to the user.

Some Details

I access the user’s location when they first navigate to the site. The WebAPI has documentation on how the geolocation object behaves, but the basics are pretty straight forward. You ask for the latitude and longitude, the browser then asks the user if that is ok, and if they accept, an asynchronous request is made which returns an object that contains that information. I used a great library to modify the geolocation behavior into something more React savvy. React-Geolocated allows you to wrap an existing component, passing the geolocation details as props. This makes accessing and reasoning with the latitude and longitude as simple as

1
2
const lat = props.coords.latitude;
const long = props.coords.longitude;

React’s componentWillReceiveProps method makes it a simple matter to wait for the location data to load as well. It will run when the props are updated in the app with the coordinates of the user:

1
2
3
4
5
componentWillReceiveProps(nextProps) {
if (nextProps.coords !== null) {
useUserLocationToMakeADifference(coords);
}
}

The Sunlight Foundation’s Congress API is a really exciting tool. Although they’ve announced recently that they are moving over management of this API to ProPublica, it is still currently hosted at their old URL and doesn’t require an API key to function. I’m not sure what the timeline is on this transition, but both parties have been quick to respond to any inquiries I’ve had about the API and are obviously doing great civic work by giving free access of this data to the public. The call I’m making to the API is very straightforward. After I have the user’s location, I simply format that into a request like this

1
2
3
4
5
6
7
8
9
    fetch(`https://congress.api.sunlightfoundation.com/legislators/locate?latitude=${lat}&longitude=${long}`)
```

At this point it’s just a matter of formatting and presenting the response data. I pull out the relevant data from the results objects, in this case the name, phone number, and email address of each legislator. I wrote some helper methods that I won’t detail here, but the basic implementation looks a like this

```js
extractName(this.state.repArray[0])
extractPhone(this.state.repArray[0])
extractEmail(this.state.repArray[0])

Finally, I used an interesting trick that my mentor, Brian Douglas, showed me for rigging up an ajax spinner while the data is being fetched. When the component is mounted, the repArray is set to null, so I can use that state to track when the data is ready to display by using a ternary operator to render either the data or a loader.

    render () {
        return this.state.repArray ?
            <LegislatorData 1>
            <LegislatorData 2>
            <LegislatorData 3>
        : <AjaxLoader>
    }

Next Steps

Midway through the development of YWFM I was fortunate enough to get a job. Between moving to Madison, WI and getting ramped up on a new technology stack, I had to put the development of several features on hold. Probably the most pressing need is to allow the user to enter their own location if they don’t want to or cannot allow the browser to access their physical location. My goal was to get the legislative contact information in front of a user in as few steps as possible, but now I need to gracefully handle that absence of the user’s location. Along the lines of “basic usability,” the app doesn’t look fantastic on mobile devices at the moment, so some work needs to be done on adjusting the styling and formatting to account for different screen sizes. I want to have the option for a user to set up reminders to call their representatives regularly. Either by having an option to populate a calendar on the device used to access the data, regular email reminders, or setting up text reminders with a service like Twilio. I think it would be interesting to be able to present recent congressional activity, whether that is votes or other recorded data. This could simply be displayed at the landing page for each legislator, or a user could similarly opt in to text or email notifications. Adding more features to the core features of the app could potentially complicate the management of state, so I am interested in adding the Redux library as a way to manage state in the app. If the idea of civic engagement through programming is interesting to you, let’s get involved! Help with any of the features above, other ideas, or even just a little help refactoring are more than welcome. Let’s work together to make it easier for citizens to tell their legislators: “You work for me!”

Separating the Location Features

You Work for Me is an app I’m building as a way to learn React. YWFM uses the Web API’s geolocation capabilities alongside the Sunlight Lab Congress API to determine the user’s congressional representatives, supplying them with contact information. My mentor, Brian, and I decided that the functionality that determines the location and correct legislators would be a good candidate to abstract away from this app into a separate library. I decided to use the SurviveJS component boiler plate to generate the base for my library. I made this decision for the sake of time. I know I will learn a lot when I set up my own boilerplate, but for now I’d rather have my project ready to demonstrate at an interview than get stuck in the weeds trying to configure a whole mess of dependencies just to get off the ground. The SurviveJS boilerplate is very simple to set up. As per their instructions, just clone the repo, remove the .git file and run git init to hook up the cloned folder to your own repository instead. Finally, use npm install to install the dependencies. I want to hone down my library to do one specific task really well, so rather than offering a suite of location based services, the library will provide the congressional district of the user, based on the location returned by the Geolocation API. Because a user must give the browser permission, the library needs to have a graceful default if permission isn’t granted or if geolocation isn’t enabled or possible for some reason. The first steps I need to complete in order to have this library functioning are as follows:

  • Test the API that returns district numbers, seeing what form the returned data takes

  • Insert that API into my current app to bring in the district numbers

  • ID the correct rep. for the user and provide their contact information

After some ugly moments in which I remembered how much fun it is to play with promises in JavaScript, the API is finally returning what I need: an object with state and district values. This example uses the JavaScript Fetch API to issue a call to the Sunlight Labs’ district lookup method. We pass in the sample latitude and longitude (or replace with your own) from the API documentation. This call returns a promise object, so we’ll use the .then method to pass a callback that waits for the response object and then calls .json() on it when received. Because .json also returns a promise, we’ll use .then() again and just log the results of our response so we can look at it. If you’re following along, you can test the logic right now. Just open the developer tools in your browser and try out the commands below:

1
2
3
4
5
6
7
8
const lat = 42.96
const long = -108.09

fetch(\`https://congress.api.sunlightfoundation.com/districts/locate?latitude=${lat}&longitude=${long}\`).then(
(res) => res.json().then(
(jsonObject) => console.log(jsonObject.results\\\[0\\\])
)
)

(Also take a moment to appreciate how nice this looks with ES6 arrow functions!) In the following post I’ll walk through pulling out the location service, the political api, and wrapping it into a single library. I’ll also cover writing tests for that library and publishing it to NPM.

Enter the Eloquence - Eloquent JavaScript, Chapter 2

I'm aiming to bring my JavaScript chops up a level or two, and I've decided to address this first by working through all of Eloquent JavaScript by Marijin Haverbeke. I'm going to do each chapter's exercises and post them here with my thoughts. This will have the benefit of forcing me to clarify my thinking on the solutions, and it could also help someone else who might be struggling with the ideas. The book is definitely a dense read. So far, the first two chapters are written in a style that is not quite conversational and not quite formal. It has the odd effect on me of an almost instant-glaze over, which is requiring a slower reading pace. This probably exacerbated by the fact that I'm using a e-book version, not a hard copy. Slowing down my pace of reading is fine though, since I don't want to miss any details in my deep-dive into this language! So, without further ado:
Loops to Make a Triangle

1
2
3
4
5
6
7
8
9
10
11
12
13
// Looping a Triangle
// For Loop
var hashTriangle = ""
for (var i = 0; i <= 7; i++) {
hashTriangle += "#";
console.log(hashTriangle);
}
// While Loop
hashTriangle = ""
while (hashTriangle.length <= 7) {
hashTriangle += "#";
console.log(hashTriangle);
}

Not much to say here. I decided to try two simple implementations, one with a for-loop and the other with a while-loop. The Fizz Buzz Problem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Fizz Buzz
for (var i = 1; i <= 20; i ++) {
divByThree = (i % 3 == 0);
divByFive = (i % 5 == 0);

if (divByThree && divByFive) {
console.log("FizzBuzz");
}
else if (divByFive) {
console.log("Buzz");
}
else if (divByThree) {
console.log("Fizz");
}
else {
console.log(i);
}
}

Whenever I work on a FizzBuzz type of challenge, I have a nagging feeling in the back of my mind that I'm doing extremely naive work and that there is a much fancier, elegant way to solve the problem than I have discovered so far. It would seem that this is the case, but I'm not going to worry about that for now. This being my third time thinking through the problem at some length greater than 30 minutes, I'm happy with my smallish refactoring, that being that I saved the results of the modulo operations to variables to avoid repeating the operation unnecessarily. Create a Chess Board String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Chess Board String
var chessBoard = "";
var size = 8;
// set height
for (var i = 0; i < size; i++) {
// set each row
for (var j = 0; j < size / 2; j++) {
if (i % 2 == 0) {
chessBoard += "# ";
} else {
chessBoard += " #";
}
}
chessBoard += "\\n";
}
console.log(chessBoard);

This was an interesting problem to play with. I think my biggest hang-up was simply that I struggled to get away from the notion of implementing this as a 2D array, rather than a formatted string. I may come back to this, as I feel there are more interesting, compact solutions available than what I came up with. So, there are my solutions to the three exercises from Eloquent JavaScript, chapter 2. If you found interesting ways to solve any of them, please let me know. I love being shown how weak my Kung-Fu is, so have at me!

Entering the World of OSS

I am beginning the final quarter of my Bloc.io curriculum today.

This quarter is called the “Open-Source Apprenticeship,” and it asks me to create my own open-source software (OSS) project and to make ten significant contributions to other projects.

I started my coursework with Bloc almost exactly a year ago from the day I’m writing this: November 23rd, 2015. It was a huge leap of faith to trust an essentially unproven model: a web-development “bootcamp” taking place entirely online (I’ve stopped calling this a “boot-camp” for a variety of reasons that I’ll be writing about later). But I girded my loins and made the last step in a pivot away from my music career diving in head first to 40+ hour weeks full of study, practice, and 1-on-1 meetings with my mentors.

In that time I’ve learned so much! My coursework covered Back-End and Front-End web development technologies, mainly Ruby, Rails, Javascript, JQuery, and AngularJS. It focused on lots of “non-coding software developer skills,” like version control with git and GitHub, test-driven development with RSpec, and tons of code review and pair-programming with my professional mentors. In my third quarter, which I just finished, I got a chance to learn about the bigger-picture topics that are covered in computer science courses. I implemented many of the common data structures and algorithms, built an ORM reminiscent of Active Record, and made a Rails clone in order to better understand the decisions web engineers make in organizing code, handling routing concerns, and setting up a framework to handle the traditional MVC model.

So, with all that work behind me now, the prospect of jumping into the OSS community to see what I can accomplish is exciting, to say the least. I’ve been brainstorming on several different personal projects that have potential and taking note of tools that I use frequently that I could start to contribute to myself.

Some other goals I have for myself for the next three months are:

  • level up my Javascript skills
  • investigate different JS frameworks
  • find a great testing suite for Javascript development
  • making Pry another component of my Ruby debugging process
  • go to Chicago at least twice a month to meet other developers
  • clean up my prior projects from Bloc for my portfolio