Variables & Data Types

Always use var, let, or const. Omitting those keywords results in global variables, which is bad! Only use let or const in ES2015+/TypeScript.

/* bad! */
foo = 1;
foo = "hi";
/* good! */
var foo = "hi";

String, Number, Boolean, Object, Function, null and undefined

Use typeof to determine the type of a particular value.

typeof 1.4; /* returns "number" */
typeof "hi"; /* returns "string" */

Use instanceof to determine the constructor of an Object. (This is not necessarily always going to work.)

Operators

Usual arithmetic applies with the usual ordering. We have access to +, -, /, *, %.

Usual boolean comparisson operators exist as well. We may use <, >, , >= as usual.

However, if we wish to check equality, we should always use the === or !== operator to ensure that the underlying type of the objects we’re comparing are the same. You should probably ensure that your linter is set to tell you this.

Conditionals & Loops

Conditionals

If requires parens and the else if has a space between the else and if:

if (boolean) {
	// do something
} else if (otherBoolean) {
	// do something else
} else {
	// catch all
}

Always use curly braces in your block statments.

Loops

Loops operate mostly normal. We have for, while, and do.. while.

for (var i = 0; i < 10; i++) {
	console.log(i);
}

In addition to this, we have a for…​ in stament that makes looping over arrays slightly nicer:

var a = [1,2,3,4,5];
for (var idx in a) {
	console.log(a[idx]);
}

for (var i = 0; i < a.length; i++) {
	var x = a[i];
	console.log(x);
}

You may use continue and break to control loops.

Functions

Functions exist as you might expect. They have names and arguments, and they may return a single value.

function add(x, y) {
	return x + y;
}

console.log(add(3, 4));

We also have anonamous functions:

function(x, y) {
	return x + y;
}

var add = function(x, y) {
	return x + y;
}

add(3, 4);

(function(x, y) {
	return x + y;
})(3, 4);

var add = function add(x, y) {
	return x + y;
}

Functions are value types. This means We can store functions in objects.

var o = {
	pi: 3.14159,
	add: function(x,y) {
		return x+y;
	},
	times2: function times2(x) {
		return x*2;
	},
	circumference: function(r) {
		return this.times2(this.pi * r);
	}
};

Scope

Javascript is function scoped.

function doThing(x) {
	if (x < 0) {
		var x = 5; /* this is not a new variable */
		console.log(x);
	}
	console.log(x);
}

If I wanted the x inside of the if statement to be only scoped inside the if statement:

function doThing(x) {
	if (x < 0) {
		(function() {
			var x = 5; /* this IS a new variable */
			console.log(x);
		})()
	}
	console.log(x);
}

THIS is special

In the following code, this does not have a times2 or pi property.

var o = {
	pi: 3.14159,
	add: function(x,y) {
		return x+y;
	},
	times2: function times2(x) {
		return x*2;
	},
	circumference: function(r) {
		var self = this;
		return function() {
			return this.times2(this.pi * r);
		}();
	}
};

To fix this, we must store this in a temporary variable. It is conventional to use the self variable.

var o = {
	pi: 3.14159,
	add: function(x,y) {
		return x+y;
	},
	times2: function times2(x) {
		return x*2;
	},
	circumference: function(r) {
		var self = this;
		return function() {
			return self.times2(self.pi * r);
		}();
	}
};

Arguments

function (a, b, c) {
	return a+b+c;
}
function () {
	var a = arguments[0],
		b = arguments[1],
		c = arguments[2];

	return a+b+c;
}

Prototypes

Javascript is prototypical. This means that we don’t define classes, we define objects that "look" the way we want.

function MathLib(pi) {
	this.pi = pi;
}

MathLib.prototype.add = function add(x, y) {
	return x+y;
}

MathLib.prototype.times2 = function times2(x) {
	return x*2;
}

var m = new MathLib(3.14);
m.add(6, 8);
m.pi;

Gotchas

Semicolons

function foo() {
	return { "bar": "baz" }
}
function foo() {
	return {
		"bar": "baz"
	}
}
function foo() {
	return
	{
		"bar": "baz"
	}
}

USE A LINTER: