This post gives an overview of JavaScript that is as short as possible, but explains every major feature. Give the language a chance! You have to learn its quirks, but then it is fun to program in.
Comments:
// a single-line comment (at the end of a line) /* A multi-line comment (anywhere) */Various statements:
console.log("hello"); // print something var myvar = 7; // declare a variable
function twice(x) { return 2 * x; } console.log(twice(4)); // 8
var obj = { propName1: 123, propName2: "abc" } obj.propName1 = 456; obj["propName1"] = 456; // same as previous statementDon’t mistake JavaScript objects for simple maps (dictionaries)! They can be used as maps from strings to values, but they are also real objects. Object literals are one of JavaScripts standout features: They allow you to directly create objects – no classes necessary. That is true object-orientation: You can start with concrete objects and introduce abstractions later, as needed. The abstraction for an object factory is a class in most mainstream languages, in JavaScript it is the constructor function (see below).
var arr = [true, "abc", 123]; console.log(arr[1]); // abc console.log(arr.length); // 3
function foo() {} foo.bar = 123;
> typeof 123 'number' > typeof true 'boolean' > typeof {} 'object'All other types are object types. You test whether a value is an instance of a given type via instanceof:
> 123 instanceof Object false > {} instanceof Object trueNote that, apart from typeof and instanceof, the difference between primitives and objects is practically unnoticeable in JavaScript.
> var x; > typeof x === "undefined" true > typeof undeclaredVariable === "undefined" trueProgrammers should prefer null for this purpose:
function someFunction(x) { // test for null: if (x === null) { // ... } } someFunction(null);Because both undefined and null are interpreted as false by an if statement, you can check for either value as follows:
function hasAValue(x) { if (x) { // x is neither undefined nor null return "YES"; } else { return "NO"; } }Beware: All of the following values are interpreted as false. If you check for a value via hasAValue() then, for example, 0 is not considered a value.
> hasAValue(undefined) 'NO' > hasAValue(null) 'NO' > hasAValue(0) 'NO' > hasAValue("") 'NO' > hasAValue({}) 'YES' > hasAValue([]) 'YES'
Equals | myvar === "abc" |
Not equals | myvar !== "def" |
Less than | myvar < 10 |
Less or equals | myvar <= 10 |
Greater | myvar > 0 |
Greater or equals | myvar >= 0 |
Boolean operators:
Not | !myvar |
And | 0 <= a && a < arr.length |
Or | a === "foo" || a === "bar" |
if (myvar === 3) { // then } else { // else }In the following switch statement, the value of fruit decides which case is executed.
switch (fruit) { case "banana": // ... break; case "apple": // ... break; default: // ... }
for(initialization; loop while this condition holds; next step)Example:
for (var i=0; i < arr.length; i++) { console.log(arr[i]); }The while loop continues looping over its body while its condition holds.
// Same as for loop above: var i = 0; while (i < arr.length) { console.log(arr[i]); i++; }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.
do { // ... } while(condition);In all loops:
function foo(x) { x++; if (x > 100) { var tmp = x - 100; } }Due to hoisting, the above code is equivalent to
function foo(x) { var tmp; x++; if (x > 100) { tmp = x - 100; } }You should be fine, as long as you remember that JavaScript is function-scoped: Wherever a variable is declared, its scope is the complete innermost enclosing function. You can simulate a block by defining a function and immediately invoking it.
function foo(x) { x++; if (x > 100) { (function () { // The rest of foo can’t access tmp var tmp = x - 100; }()); } }This pattern is called an IIFE (immediately-invoked function expression) and pronounced “iffy”. Notes:
[3, 4, 5].forEach(function (elem) { console.log(elem); });
var jane = { name: "Jane", // a method: sayHello: function () { return this.name + " says 'hello'" } }; console.log(jane.sayHello()); // Jane says 'hello'A method is a property whose value is a function. For example, sayHello() in the code above. In contrast to many mainstream languages, JavaScript lets you directly work with objects. That is very handy, because you can work with concrete objects first and introduce abstractions (constructors in JavaScript, classes in most other languages) later on.
function beep(callback) { console.log("beep"); callback(); } var counter = { count: 0, beepAndInc: function () { var that = this; beep(function () { // the function shadows counter’s "this" // => must use "that" that.count++; }); } }Array iteration methods have a second parameter that allows you to specify a value that is to be used for this:
var jane2 = { name: "Jane", logHello: function (friends) { friends.forEach(function (friend) { console.log(this.name + " says hello to " + friend) }, this); } }
function repeat(n, func) { for(var i = 0; i < n; i++) { func(); } } var counter = { count: 0, inc: function () { this.count++; } }When calling repeat(), you might be tempted to hand it counter.inc:
> repeat(2, counter.inc)However, that doesn’t work:
> counter.count 0The reason is that by accessing the value of counter.inc, you have turned the method into a function. Then this does not point to counter, any more and counter.count does not get incremented. The solution is to use the bind() method that every function has. It creates a new function where this has the value specified by its first argument.
> repeat(2, counter.inc.bind(counter))This time, everything worked fine:
> counter.count 2
// The constructor sets up an instance function Person(name) { this.name = name; } // The prototype property of the constructor holds an object whose // properties are shared between all instances (usually methods) Person.prototype.sayHello = function () { return this.name + " says 'hello'" }; var jane = new Person("Jane");Extending a constructor is non-trivial. You can either do it yourself or use an API. Note that you don’t need inheritance as often in JavaScript, because you can add arbitrary properties to an instance.
"use strict";Older versions of ECMAScript simply ignore the above statement.