Apr 27, 20164 min read

5 things every JavaScript developer should know

New JavaScript frameworks ship every day, and it's easy to neglect the language's core concepts. Here are five fundamentals every JavaScript developer should know.


5 things every JavaScript developer should know

Introduction

New JavaScript frameworks ship every single day, and it's easy for a lot of people (myself included) to neglect the language's core concepts. As part of my own studying, I decided to put together this quick rundown of a few ideas I consider fundamental for any JavaScript developer.

1. Scopes

Scopes in JavaScript work differently from most other languages whose syntax is influenced by C. In those languages, scope is delimited by blocks (usually created with curly braces).

In JavaScript, scopes are declared by functions, not by blocks. A declaration created inside a block isn't torn down at the end of that block the way it would be in other languages.

Consider the following code:

if (window) {
  var x = 123
}
console.log(x)

If you're coming from another language and just started learning JavaScript, you probably expect the result to be undefined. But if you run this code, the result is 123 — JavaScript doesn't close scopes at the end of a block.

2. Hoisting

Take a look at this example:

var x = 123
function f() {
  console.log(x)
  var x = 321
  console.log(x)
}
f()

You probably expect 123 to be printed in the first log and 321 in the second. In reality, the first log prints undefined. That's because, inside the function, the local scope takes precedence over the global scope. Local variables shadow any global variable with the same name. At the first log, x hasn't been assigned yet, but it already exists in the local scope thanks to a special behavior called hoisting.

When a function is declared, every variable declared inside it (no matter where) is moved (hoisted) to the top of the function. Only the declaration is moved, though — any assignments stay exactly where they are. In the example, the local variable's declaration is hoisted to the top but its assignment is not. So the equivalent code would be:

var x = 123
function f() {
  var x
  console.log(x) // undefined
  x = 321
  console.log(x) // 321
}
f()

3. Invocations

In JavaScript there are four ways to invoke a function, and each one has a huge impact on how the code inside behaves — especially on the this parameter. These ways are:

  • As a function, invoked directly;
  • As a method, which binds the invocation to an object, enabling object-oriented programming;
  • As a constructor, where a new object is instantiated;
  • Through its apply() or call() methods.

JavaScript allows the number of arguments to differ from the number of parameters. Extra arguments beyond the number of parameters are ignored. If there are more parameters than arguments, the parameters without a matching argument are set to undefined.

On top of that, every function invocation also receives two implicit parameters: arguments and this. They can be referenced inside the function just like any other explicitly named parameter.

4. Closures

A closure is the scope created when a function is declared that lets the function access and manipulate variables outside of it. This allows a declared function to be called at any point in the future, even after the scope in which it was declared is long gone.

Let's look at this example:

var outerValue = '123'
var later

function outerFunction() {
  var innerValue = '321'

  function innerFunction() {
    console.log(outerValue)
    console.log(innerValue)
  }

  later = innerFunction
}

outerFunction()
later()

Here the inner function runs after the outer function, through a reference held in the global variable later. By the time the inner function runs, the outer function's scope is gone and isn't visible when we call later(). That might lead you to believe innerValue would print undefined. Instead, the answer is 321 — because when we declared innerFunction(), a closure was created.

Closures capture not only the function declaration, but also every variable that was in scope at the moment of declaration. Even though the scope it was declared in is gone, the function still has access to that original scope through its closure.

So a closure creates a kind of "safety bubble" around the function and the variables in scope at declaration time, giving the function everything it needs to run.

5. Prototype

The prototype is a convenient way to define object types. It lets you define properties and behavior that apply to instances of an object. In other words, prototypes are similar to classes in object-oriented languages. When you use the prototype, every instance gets access to the methods you create. Those instances must be initialized with the new keyword.

References

  1. RESIG, John; BIBEAULT, Bear. Secrets of the JavaScript Ninja. Manning, 2013.
  2. STEFANOV, Stoyan. Object-Oriented JavaScript. Packt Publishing Ltd, 2008.