Main image of article Key Elements of Advanced JavaScript

If you want to land a job using JavaScript, you need to know it well: It’s a language that seems simple on the surface, but can get very complex very, very quickly. Messing up can result in some epic flaws—if you’re writing client-side code in the browser, for example, the browser might start freezing up at seemingly random times. The following is a short list of the advanced JavaScript topics you’ll need to know to perform your job well. (Highlighting these skills in a job interview may also help you land the position.) Let’s start with a big one: asynchronicity.

Asynchronicity

First, a brief digression: When the Ajax programming language was new, a lot of programmers were troubled by its asynchronous nature. Developers wanted to write a line of code similar to this: [js] x = ajax.send('some url'); [/js] and have "x" filled with the result from the Ajax request. That call would be synchronous; your code would stop and wait for the call to complete, and the result of the call would be stored in the variable called "x." Except it didn't work: While you could make synchronous calls, we were encouraged not to, having been told it would freeze up the browser during the call. That didn't seem like a huge deal to people at the time, considering there might only be one browser tab open, and you didn't want users clicking around and doing stuff until the call completed. But JavaScript wasn't built to function that way: It is asynchronous, as you can most clearly see with server-side JavaScript; you simply can't have your code stopping and waiting for a call to a database to finish. The JavaScript code itself only has a single thread (although the underlying system has multiple threads, which is an important point), so if you stop and wait for an I/O or database call to complete, you'll hold up other calls being made to your server. Asynchronicity is necessary. In light of that, experienced JavaScript developers use callbacks, such as this: [js] sqlpool.query('select something', function(err, resp) { // do something with the data }); nextcall(); [/js] Depending on how the query function is coded (and most likely it is coded this way), the nextcall() statement will run before the code inside the callback. People learn this technique when studying Node.js, where applications are written in JavaScript, but that's not the end of the story. Node.js maintains a queue of events. If you're writing a Web app, each event is going to be an incoming request, resulting in JavaScript code that runs in response to that code. The requests get queued up; the database calls inside the query function get pushed onto the queue, as well. Your current function finishes up from nextcall() on. Then, when your event code is finished, Node.js runs the next event, which will likely be the actual database calls (again depending on how the database code is written). And those database calls, such as in the case of the mysql2 module, will likely have multiple calls queued up. When you write your own libraries, you have two ways to handle callbacks: You can call the callback immediately, causing the callback code to get called before the statements that follow, or you can queue up the code. There are two functions for dealing with this: setImmediate and process.nextTick. (Here's a good explanation of the difference.) If you don't bother with either of these and call the callback immediately, you risk overloading the call stack, causing Node.js to crash. There's a library called async.js that can help you manage all your callbacks. But understanding everything explained above is vital to using async.js correctly. Even if you never encounter a stack error, you want to be aware of the differences, and how async.js’s “series” function works, as opposed to its “parallel” function. (I put them in quotes because they're actually synchronous vs. asynchronous. Look at the source code and you'll see. The series function calls the callback directly.) As you can see, learning the fundamentals of asynchronicity—not just how to make Ajax calls, but what really goes on under the hood—is vital to understanding JavaScript. This applies not just to Node.js, but to code that runs in your browser, as well. (For what it's worth, you can use async.js in your browser code, and I often do.)

Strict Mode

I'm going to admit something here: It took me a while to embrace strict mode. Now I use it because, quite honestly, I had started developing what I felt were best practices to avoid problems in my code, and it turns out that strict mode enforces many such best practices. Strict mode enforces clean code that is less likely to have bugs. For example, JavaScript allows you to forget to declare a variable with the var keyword, and just start using that variable. When JavaScript encounters such a variable, it doesn't actually make the variable global (as some people think); rather, it adds the variable to the global object. In the browser, the global object is accessible through the variable name window. For example, save the following code in a file and open it in Chrome: [js] <html> <head> <script> x = 10; </script> </head> <body></body> </html> [/js] Press F12 and look at the console. Type x. You'll see its value, 10, as if it's a global variable. Now type window.x, and you'll see it's actually a member of the global object, window. If you forget to use var, your global object will quickly get dozens of variables that aren't meant to be global. Then, if you reuse the same variable name within your functions, you could have bugs if the variable already exists. To prevent such bugs, turn on strict mode. Change the code inside the script element to this: [js] 'use strict' x = 10; [/js] Keep the page open and reload it. You'll see an error:

Uncaught ReferenceError: x is not defined

Strict mode has many other features, and you can learn about them here and here.

Tools

If you want to land a job that uses JavaScript, you have to know not only the language itself, but the tools. This means if you're learning Node.js, you must know how to use npm, including how to find packages in it, and how to test out packages to determine which is the best fit for your app. (Don't just assume the most popular is the best fit.) You also need to know how to use the package.json file in your application, and how to keep it updated. And you probably don't want to check in your node_modules directory into source control, but rely instead on the package.json and npm install command for installing your app on a new machine. Further, you need to know how to use the debuggers (Firebug, Chrome's tools, etc.), and how to profile your application (in Chrome, press F12, and then go to the Profiles tab). Is your app eating up boatloads of memory? You'll need to know how to take a heap snapshot and drill into it to determine where the problems are. And beyond tools, take a look at other people's code. Look through the async.js code and see how it works. The source is all there. Look at the code for the database drivers such as mysql2 and MongoDB and learn how it all works. Also look at the request.js code. Study from the greats and learn their best practices.

Conclusion

Think you're ready for advanced JavaScript? Take a look at this page on jQuery creator John Resig's site; everything on his list should be familiar to you. Other features you should know include:

  • How to use apply, bind, and call
  • Why eval is dangerous
  • How to parse JSON
  • How to use the ES5 and ES6 features

Why didn't I explain closure in this article? If you're ready for the topics in this article, you should already understand closure (and its pitfalls with loops) inside and out. Good luck!