2013-06-22

What is the best way to learn JavaScript? If you haven’t programmed before, you first have learn what programming is. If you are a programmer, though, you can take a shortcut: You already know many programming language constructs and just need to learn how they are expressed in JavaScript.

Assuming that you are a programmer, the goal of this blog post is to get you started with JavaScript as quickly as possible. It describes the smallest subset of the language that allows you to be productive. I call that subset “Basic JavaScript” and recommend to program in it for a while, before moving on to more details and advanced topics. Learning everything at once is too confusing. This blog post concludes with tips for what to learn next.

Warning: Below, I’m describing rules of thumbs and best practices. I favor clarity over precision (e.g., whenever you see the word “roughly”). The rules are safe, but – unavoidably – a matter of taste.

Table of contents

1.

Conventions used in this blog post

2.

The character of the language

3.

Syntax

4.

Variables and assignment

5.

Values

6.

Booleans

7.

Numbers

8.

Strings

9.

Statements

10.

Functions

11.

Exception handling

12.

Strict mode

13.

Variable scoping and closures

14.

Objects and inheritance

15.

Arrays

16.

Regular expressions

17.

Math

18.

Other functionality of the standard library

19.

What to learn next?

Conventions used in this blog post

Command line interaction

Whenever I introduce a new concept, I also try to illustrate it via an interaction in a JavaScript command line. This looks as follows:

The text after the greater-than character is the input, typed by a human. Everything else is output by the JavaScript engine. Additionally, the method console.log() is sometimes used to print data to the console (this method works in most JavaScript environments, including Node.js).

Finding documentation

Sometimes, you see functions and methods in action, which should make it clear how they work. If not, there are links to pages of the Mozilla Developer Network (MDN), where you can look up the details. Additionally, you can use Google to find documentation on MDN. For example, the following Google search finds the documentation for the push() method of arrays:

The character of the language

JavaScript’s creator, Brendan Eich, had no choice but to create the language very quickly (or other, worse, technologies would have been used at Netscape). He borrowed from several programming languages:

Java is the cause of JavaScript’s syntax and of how it partitions values into primitives and objects.

Scheme and AWK inspired JavaScript’s handling of functions – they are first-class and used frequently in the language. Closures make them a powerful tool.

Self is responsible for JavaScript’s unique style of object-oriented programming (OOP). Its core (which we can’t go into here) is elegant, some of the things built on top of that core are less so. But a simple pattern (shown later) takes care of most use cases. A killer feature of JavaScript OOP is that you can create objects, directly. There is no need to create a class or something similar first.

Perl and Python influenced JavaScript’s handling of strings, arrays and regular expressions.

JavaScript did not have exception handling until ECMAScript 3, which explains why the language so often automatically converts values and so often fails silently: it initially couldn’t throw exceptions.

On one hand, JavaScript has quirks and is missing quite a bit of functionality (block-scoped variables, modules, support for subtyping, etc.). On the other hand, it has several powerful features that allow you to work around these problems. In other languages, you learn language features. In JavaScript, you often learn patterns, instead.

Further reading

JavaScript: how it all began

JavaScript: the glass is half full [what makes JavaScript appealing?]

ECMAScript: ES.next versus ES 6 versus ES Harmony [includes a brief history of ECMAScript versions]

Perl and Python influences in JavaScript

Syntax

First, a few general points on JavaScript’s syntax.

Statements versus expressions

To understand JavaScript’s syntax, it helps to know that (simplifyingly), it has two major syntactic categories: statements and expressions.

Statements “do things”. A program is a sequence of statements. Example of a statement, which declares (creates) a variable foo:

Expressions produce values. They are the right-hand side of an assignment, function arguments, etc. Example of an expression:

The distinction between statements and expressions is best illustrated by the fact that JavaScript (like Java) has two different ways to do if-then-else. Either as a statement:

Or as an expression:

You can use the latter as a function argument (but not the former):

Lastly, wherever JavaScript expects a statement, you can also use an expression. For example:

foo(...); is a statement (a so-called expression statement), bar(7, 1) is an expression. Both are function calls.

Control flow statements and blocks

For control flow statements, the body can be a single statement. Two examples:

However, any statement can always be replaced by a block, curly braces containing zero or more statements. Thus, you could also write:

In this blog post, we only use the latter form of control flow statements.

Semicolons

Semicolons are optional in JavaScript. But omitting them can lead to surprises, which is why I recommend against doing it.

As you can see above, semicolons terminate statements, but not blocks. There is one case where you will see a semicolon after a block: A function expression is an expression that ends with a block. If such an expression comes last in a statement, it is followed by a semicolon:

Comments

JavaScript has two kinds of comments: single-line comments and multi-line comments. Single-line comments start with // and are terminated by the end of the line:

Multi-line comments are delimited by /* and */

Further reading

Expressions versus statements in JavaScript

Automatic semicolon insertion in JavaScript

Variables and assignment

Variables in JavaScript must be declared, before they can be used:

Assignment

You can declare a variable and assign a value at the same time:

You can also assign a value to an existing variable:

Compount assignment operators

There are compound assignment operators such as +=. The following two assignments are equivalent:

Legal variable names

Identifiers are names for things, they play various syntactic roles in JavaScript. For example, the name of a variable is an identifier.

Roughly, the first character of an identifier can be any Unicode letter, a dollar sign ($) or an underscore (_). Later characters can additionally be any Unicode digit. Thus, the following are all legal identifiers:

Several identifiers are “reserved words” – they are part of the syntax and can’t be used as variable names:

arguments break case catch class const continue debugger default delete do else enum eval export extends false finally for function if implements import in instanceof interface let new null package private protected public return static super switch this throw true try typeof var void while with yield

Technically, the following three identifiers are not reserved words, but shouldn’t be used as variable names, either:

Infinity NaN undefined

Further reading

Valid JavaScript variable names [by Mathias Bynens]

Values

JavaScript has all the values that we have come to expect from programming languages: booleans, numbers, strings, arrays, etc. All values in JavaScript have properties. Each property has a key (or name) and a value. Think fields of a record. The key is a string, the value is any JavaScript value.
You use the dot (.) operator to read a property:

An example:

The above is equivalent to:

The dot operator is also used to assign a value to a property:

And you can invoke methods via it:

Above, we have invoked the method toUpperCase() on the value 'hello'.

Primitive values versus objects

JavaScript partitions its values into primitive values (short: primitives) and objects. That partitioning is somewhat arbitrary: primitives are mostly objects that behave somewhat differently (the next section explains how). There is no restriction where you can use either kind of value. Sometimes the difference does matter, so you have to know which is which, but it’s not difficult to remember.

The following are all of the primitive values (short: primitives):

Booleans: true, false

Numbers: 1736, 1.351

Strings: 'abc', "abc"

Two “non-values”: undefined, null

All other values are objects. The most common kinds of objects are:

Plain objects can be created by object literals:

The above object has two properties: The value of property firstName is 'Jane', the value of property lastName is 'Doe'.

Arrays can be created by array literals:

The above array has three elements that can be accessed via numeric indices. For example, the index of 'apple' is 0.

Regular expressions: can be created by regular expression literals:

You can define new kinds of objects, but you can’t define new kinds of primitives.

Differences between primitives and objects

The differences are subtle. Feel free to skim and come back after you have seen more of primitives and objects.

Primitives are:

compared by value: the content is compared.

always immutable: the values of properties can’t be changed, no properties can be added or removed.

(Reading an unknown property always returns undefined.)

a fixed set of values: you can’t define your own primitives.

Objects are:

compared by reference: identities are compared, every value has its own identity.

mutable by default.

user-extensible: you can define new object types, via constructors.

All data structures (such as arrays) are objects, but some objects are decidedly not data structures (for example, regular expressions).

undefined and null

Somewhat unnecessarily, JavaScript has two “non-values”: undefined and null.

undefined means “no value”. Uninitialized variables are undefined:

If you read a non-existant property, you also get undefined:

Missing parameters are undefined, too:

null means “no object”. It is used as a non-value when an object is expected (parameters, last in a chain of objects, etc.).

Normally, you should treat undefined and null equivalently, as if they were the same non-value. One way of checking for them is via an explicit comparison:

Another way is to exploit the fact that both undefined and null are considered false:

Warning: false, 0, NaN and '' are also considered false.

Wrapper types

JavaScript has three types that are named after the primitive types, but whose instances are objects: Boolean, Number and String.
You will likely never create or encounter instances of them, but they are useful in two ways:

Purpose 1: They provide the methods for primitive values:

Purpose 2: They can be used to convert values to a primitive type:

Categorizing values via typeof and instanceof

There are two operators for categorizing values: typeof is mainly used for primitive values, instanceof is used for objects.

typeof looks like this:

It returns a string describing the “type” of value. Examples:

The following table lists all results of typeof.

Operand

Result

undefined

'undefined'

null

'object'

Boolean value

'boolean'

Number value

'number'

String value

'string'

Function

'function'

All other values

'object'

Two things contradict what we have said about primitives versus objects:

The type of a function is 'function' and not 'object'. Given that Function (the type of functions) is a subtype of Object (the type of objects), this isn’t wrong.

The type of null is 'object'. This is a bug, but one that can’t be fixed, because it would break existing code.

instanceof looks like this:

It returns true if value is an object that has been created by the constructor Constr (think: class). Examples:

Further reading

Categorizing values in JavaScript

Improving the JavaScript typeof operator

Booleans

The primitive boolean type comprises the values true and false. The following operators produce booleans:

Binary logical operators: && (And), || (Or).

Prefix logical operator: ! (Not)

Equality operators: === !== == !=

Ordering operators (for strings and numbers): > >= < <=

Truthy and falsy

Whenever JavaScript expects a boolean value (e.g. for the condition of an if statement), any value can be used. It will be interpreted as either true or false. The following values are interpreted as false:

undefined, null

Boolean: false

Number: -0, NaN

String: ''

All other values are considered true. Values interpreted as false are called falsy, values interpreted as true are called truthy. Use Boolean as a function to test how a value is interpreted.

Binary logical operators

Binary logical operators in JavaScript are short-circuiting – if the first operand suffices for determining the result, the second operand is not evaluated. For example, in the following code, the function foo() is never called.

Furthermore, binary logical operators return either one of their operands – which may or may not be a boolean. A check for truthiness is used to determine which one:

And: If the first operand is falsy, return it. Otherwise, return the second operand.

Or: If the first operand is truthy, return it. Otherwise, return the second operand.

Equality operators

To check equality in JavaScript, you can either use strict equality (===) and strict inequality (!==). Or you can use lenient equality (==) and lenient inequality (!=). Rule of thumb: Always use the strict operators, pretend that the lenient operators don’t exist. Strict (in)equality is much safer.

Further reading

Equality in JavaScript: === versus ==

When is it OK to use == in JavaScript?

Numbers

All numbers in JavaScript are floating point (although most JavaScript engines internally also use integers):

Special numbers:

NaN (“not a number”): an error value.

Infinity: also mostly an error value.

Infinity is sometimes useful, because it is larger than any other number. Similarly, -Infinity is smaller than any other number.

-0: JavaScript has two zeros, +0 and -0. It normally does not let you see that and displays both as simply 0:

Therefore, it is best to pretend that there is only a single zero (as we have done when we looked at falsy values: both -0 and +0 are falsy).

Operators

JavaScript has the following arithmetic operators:

Addition: number1 + number2

Subtraction: number1 - number2

Multiplication: number1 * number2

Division: number1 / number2

Remainder: number1 % number2

Increment: ++variable, variable++

Decrement: --variable, variable--

Negate: -value

Convert to number: +value

The global object Math provides more arithmetic operations, via functions.

JavaScript also has operators for bitwise operations (e.g. bitwise And).

Further reading

There is a series of 2ality blog posts on numbers, covering topics such as:

How numbers are encoded in JavaScript

JavaScript’s two zeros

Integers and shift operators in JavaScript

NaN and Infinity in JavaScript

Working with large integers in JavaScript

Strings

Strings can be created directly via string literals. Those literals are delimited by single or double quotes. The backslash (\) escapes characters and produces a few control characters. Examples:

Single characters are accessed via square brackets:

The property length counts the number of characters in the string:

Reminder: strings are immutable, you need to create a new string if you want to change an existing one.

String operators

Strings are concatenated via the plus (+) operator, which converts the other operand to string if one of the operands is a string.

To concatenate strings in multiple steps, use the += operator:

String methods

Strings have many useful methods. Examples:

Further reading

String concatenation in JavaScript

JavaScript: single quotes or double quotes?

Statements

Conditionals

The if statement lets a boolean condition decide between a then clause and an (optional) else clause:

In the following switch statement, the value of fruit decides which case is executed.

Loops

The for loop has the format

for(initialization; loop while this condition holds; next step)

Example:

The while loop continues looping over its body while its condition holds.

The do-while loop continues looping over its body while its condition holds. As the condition follows the body, the body is always executed at least once.

In all loops:

break leaves the loop.

continue starts a new loop iteration.

Functions

One way of defining a function is via a function declaration:

The above code defines a function add that has two parameters param1 and param2 and returns the sum of both parameters. This is how you call that function:

Another way of defining add() is via a function expression:

A function expression produces a value and can thus be used to directly pass functions as arguments to other functions:

Function declarations are hoisted

Function declarations are hoisted, moved in their entirety to the beginning of the current scope. That allows you to refer to functions that are declared later:

Note that while var declarations are also hoisted, assignments performed by them are not:

The special variable arguments

You can call any function in JavaScript with an arbitrary amount of arguments – the language will never complain. It will, however, make all parameters available via the special variable arguments. arguments looks like an array, but has none of the array methods.

Too many or too few arguments

Let’s use the following function to explore how too many or too few parameters are handled in JavaScript (function toArray() is shown later).

Additional parameters will be ignored (except by arguments):

Missing parameters will get the value undefined:

Optional parameters

The following is a common pattern for assigning default values to parameters:

In line (*), the || operator returns x if it is truthy (not: null, undefined, etc.). Otherwise, it returns the second operand.

Enforcing an arity

If you want to enforce an arity, you can check arguments.length:

Converting arguments to an array

arguments is not an array, it is only array-like: It has a property length and you can access its elements via indices in square brackets. You cannot, however remove elements or invoke any of the array methods on it. Thus, you sometimes need to convert it to an array. Which is what the following function does.

Further reading

JavaScript quirk 5: parameter handling

Exception handling

The most common way of exception handling is shown below.

The try clause surrounds critical code, the catch clause is executed if an exception is thrown inside the try clause.

Further reading

Subtyping JavaScript builtins in ECMAScript 5 [especially relevant for errors]

Strict mode

Strict mode enables checks and a few other measures that make JavaScript a slightly cleaner language. It is recommended to use it. To do so, make this the first line of a JavaScript file or a script tag:

You can also switch on strict mode per function, by putting the above code at the beginning of a function:

The following two sub-sections look at the three great benefits of strict mode.

Explicit errors

Let’s look at an example where strict mode gives us an explicit error, where JavaScript otherwise fails silently: The following function f() does something illegal, it tries to change the read-only property length that all strings have:

When you call that function, it fails silently, the assignment is simply ignored. Let’s change f() so that it runs in strict mode:

Now we get an error:

this in non-method functions

In strict mode, the value of this in non-method function is undefined:

In non-strict mode, the value of this is the so-called global object (window in browsers):

No auto-created global variables

In non-strict mode, JavaScript automatically creates a global variable if you assign to a non-existing variable:

In strict mode, you get an error:

Further reading

JavaScript’s strict mode: a summary

Variable scoping and closures

In JavaScript, you must declare variables via var before you can use them:

You can declare and initialize several variables with a single var statement:

But I recommend to use one statement per variable. Thus, I would rewrite the previous statement to:

Due to hoisting (see below), it is usually best to declare variables at the beginning of a function.

Variables are function-scoped

The scope of a variable is always the complete function (as opposed to the current block). For example:

We can see that the variable tmp is not restricted to the block starting in line (*), it exists until the end of the function.

Variables are hoisted

Variable declarations are hoisted: The declaration is moved to the beginning of the function, but assignments that it makes stay put. As an example, take the variable declaration in line (*) in the following function.

Internally, this above function is executed like this:

Closures

Each function stays connected to the variables of the functions that surround it, even after it leaves the scope it was created in. For example:

The function starting in line (*) leaves the context it was created in, but stays connected to a live version of start:

A closure is a function plus the connection to the variables of its surrounding scopes. What createIncrementor() returns is thus a closure.

IIFE: Simulating block scoping

Sometimes you want to simulate a block, for example to keep a variable from becoming global. The pattern for doing so is called IIFE (Immediately Invoked Function Expression):

Above, you can see a function expression that is called right away. The parentheses prevent that it is interpreted as a function declaration; only function expressions can be immediately invoked.
The function body introduces a new scope and prevents tmp from becoming global.

Inadvertent sharing via closures

The following is a niche problem, but it can bite you hard if you are not aware of it. Thus, feel free to skim, it is enough to get a rough impression of what is going on.

Closures keep their connections to outer variables, which is sometimes not what you want:

The value returned in line (*) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value.
If you want a snapshot of the current value, you can use an IIFE:

Further reading

Variable declarations: three rules you can break

JavaScript quirk 6: the scope of variables

JavaScript quirk 7: inadvertent sharing of variables via closures

Objects and inheritance

Like all values, objects have properties and are thus maps from strings to values. Additionally, they are mutable by default.

Single objects

In JavaScript, you can directly create objects, via object literals:

Each object is a set of properties (key-value pairs, whose keys are always strings). The above object has the properties name and describe. You can read (“get”) and write (“set”) properties:

Function-valued properties such as describe are called methods. They use this to refer to the object that was used to call them.

The in operator checks whether a property exists:

If you read a property that does not exist, you get the value undefined. Hence, the previous two checks could also be performed like this:

The delete operator removes a property:

Arbitrary property keys

A property key can be any string.
So far, we have used property keys in object literals and after the dot operator. (Roughly) you can only use them that way if they are legal JavaScript identifiers. If you want to use other strings as keys, you have to quote them in an object literal and use square brackets to get and set the property:

Square brackets also allow you to compute the key of a property:

Extracting methods

If you extract a method, it loses its connection with the object. On its own, the function is not a method, any more and this has the value undefined (in strict mode).

The solution is to use the method bind() that all functions have. It creates a new function whose this always has the given value.

Functions inside a method

Every function has the special variable this. This is inconvenient if you nest a function inside a method, because you can’t access the method’s this from the function.
The following is an example where we call forEach with a function to iterate over an array:

Calling logHiToFriends produces an error:

Let’s look at two ways of fixing this. Fix #1: store this in a different variable.

Fix #2: forEach has a second parameter that allows you to provide a value for this.

Function expressions are often used as arguments in function calls in JavaScript. Always be careful when you refer to this from one of those function expressions.

Constructors: factories for objects

Until now, you may think that JavaScript objects are only maps from strings to values, a notion suggested by JavaScript’s object literals, which look like the map/dictionary literals of other languages. However, JavaScript objects also support a feature that is truly object-oriented: inheritance. This section does not fully explain how JavaScript inheritance works, but gives you a simple pattern to get you started. Consult the blog post “JavaScript inheritance by example”, if you want to know more.

In addition to being “real” functions and methods, functions play a third role in JavaScript: They become constructors, factories for objects, if invoked via the new operator. Constructors are thus a rough analog to classes in other languages.
By convention, the names of constructors start with capital letters.
Example:

To use Point, we invoke it via the new operator:

We can see that a constructor has two parts: First, the function Point sets up the instance data. Second, the property Point.prototype contains an object with the methods. The former data is specific to each instance, the latter data is shared between all instances.

Further reading

The pitfalls of using objects as maps in JavaScript [important, read soon]

JavaScript inheritance by example

Object properties in JavaScript [advanced: each property has attributes that determine whether it is writable, etc.]

Arrays

Arrays are sequences of array elements that can be accessed via integer indices starting at zero.

Array literals

Array literals are handy for creating arrays:

The above array has three elements: the strings 'a', 'b' and 'c'.
You can access them via integer indices:

Property length always indicates how many elements an array has.

But it can also be used to remove trailing elements from the array:

The in operator works for arrays, too.

Note that arrays are objects and can thus have object properties:

Array methods

Arrays have many methods. A few examples:

Iterating over arrays

There are several array methods for iterating over elements. The two most important ones are forEach and map.

forEach iterates over an array and hands the current element and its index to a function:

The above code produces the output

Note that the function in line (*) is free to ignore arguments. It could, for example, only have the parameter elem.

map creates a new array, by applying a function to each element of an existing array.

Further reading

Arrays in JavaScript

JavaScript quirk 8: array-like objects

Regular expressions

JavaScript has built-in support for regular expressions. They are delimited by slashes:

Method test(): is there a match?

Method exec(): match and capture groups

The returned array contains the complete match at index 0, the capture of the first group at index 1, etc. There is a way to invoke this method repeatedly to get all matches.

Method replace(): search and replace

The first parameter of replace must be a regular expression with a /g flag, otherwise only the first occurrence is replaced. There is also a way to use a function to compute the replacement.

Further reading

JavaScript: an overview of the regular expression API

JavaScript Regular Expression Enlightenment [by Cody Lindley]

Math

Math is an object with arithmetic functions. Examples:

Other functionality of the standard library

JavaScript’s standard library is relatively Spartan, but there are a two more things you can use:

Date:
a constructor for dates whose main functionality is parsing and creating date strings and accessing the components of a date (year, hour, etc.).

JSON:
an object with functions for parsing and generating JSON data.

console.* methods: these browser-specific methods are not part of the language proper, but some of them also work on Node.js.

What to learn next?

After you have learned the basics taught in this blog post, you can move on to the advanced material mentioned at the ends of most sections. Additionally, I recommend the following resources:

Style guides: There are many good JavaScript style guides out there. I particularly like the following two:

“Principles of Writing Consistent, Idiomatic JavaScript” by Rick Waldron and others.

Google JavaScript Style Guide

Underscore.js: a library that complements JavaScript’s minimalistic standard functionality.

JSbooks – free JavaScript books

Frontend rescue: how to keep up to date on frontend technologies

Feedback welcome

I tried my best to find an optimal subset of JavaScript that allows one to be productive. Did I succeed? Are there things that should be added or things that should be removed? I’d especially like to hear from you if you are new to JavaScript and got stuck somewhere while reading this post, or didn’t.

Show more