Update: This blog post has become a chapter in my book “Speaking JavaScript”. You can read it here: “Basic JavaScript”.

This blog post enables you to get started with JavaScript as quickly as possible – if you already know how to program. 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. The 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

Conventions used in this blog post

Command line interaction

> 3 + 4 7

console.log()

Finding documentation

push()

The nature of the language

JavaScript versus ECMAScript

Influences

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.

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 methodis sometimes used to print data to the console (this method works in most JavaScript environments, including Node.js).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 themethod of arrays:This section gives a little background on the nature of JavaScript, to help you understand why it is the way it is.The programming language is called JavaScript, the language standard is called ECMAScript. They have different names, because there is a trademark on “Java” (held by Oracle). At the moment, only Mozilla is allowed to officially use the name “JavaScript”, because they received a license long ago. Therefore, an open language standard had to have a different name. The current version of JavaScript is ECMAScript 5, ECMAScript 6 is currently being developed 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: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

Syntax

Statements versus expressions

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

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

var x; if (y >= 0) { x = y; } else { x = -y; }

var x = y >= 0 ? y : -y;

myFunction(y >= 0 ? y : -y)

foo(bar(7, 1));

foo(...);

bar(7, 1)

Control flow statements and blocks

if (obj !== null) obj.foo(); while (x > 0) x--;

if (obj !== null) { obj.foo(); } while (x > 0) { x--; }

Semicolons

This section explains a few basic syntactic principles of JavaScript.To understand JavaScript’s syntax, it helps to know that (simplifyingly), it has two major syntactic categories: statements and expressions.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:is a statement (a so-called),is an expression. Both are function calls.For control flow statements, the body can be a single statement. Two examples:However, any statement can always be replaced by a, 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 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:

var x = 3 * 7; var f = function () { };

Comments

//

x++; // single-line comment

/*

*/

/* This is a multi-line comment. */

Further reading

Variables and assignment

var foo; // declare variable `foo`

Assignment

var foo = 6;

foo = 4; // change variable `foo`

Compound assignment operators

+=

x += 1; x = x + 1;

Identifiers and variable names

JavaScript has two kinds of comments: single-line comments and multi-line comments. Single-line comments start withand are terminated by the end of the line:Multi-line comments are delimited byandVariables in JavaScript must be declared, before they can be used:You can declare a variable and assign a value at the same time:You can also assign a value to an existing variable:There are compound assignment operators such as. The following two assignments are equivalent: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:

arg0 _tmp $elem π

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

Infinity NaN undefined

Further reading

Valid JavaScript variable names [by Mathias Bynens]

Values

.

value.propKey

'abc'

length

> var str = 'abc'; > str.length 3

> 'abc'.length 3

> var obj = {}; // empty object > obj.foo = 123; // create property `foo`, set it to 123 123 > obj.foo 123

> 'hello'.toUpperCase() 'HELLO'

toUpperCase()

'hello'

Primitive values versus objects

The primitive values are: booleans, numbers, strings, null , undefined .

are: booleans, numbers, strings, , . All other values are objects. That is actually how objects are defined – all values that are not primitive.

> var obj1 = {}; // an empty object > var obj2 = {}; // another empty object > obj1 === obj2 false > obj1 === obj1 true

> var prim1 = 123; > var prim2 = 123; > prim1 === prim2 true

Primitive values

Booleans: true , false

, Numbers: 1736 , 1.351

, Strings: 'abc' , "abc"

, Two “non-values”: undefined , null

Compared by value: the “content” is compared. > 3 === 3 true > 'abc' === 'abc' true

the “content” is compared. Always immutable: the values of properties can’t be changed, no properties can be added or removed. > var str = 'abc'; > str.foo = 3; // try to create property `foo` ⇒ no effect > str.foo // unknown property undefined (Reading an unknown property always returns undefined .)

the values of properties can’t be changed, no properties can be added or removed. (Reading an unknown property always returns .) A fixed set of values: you can’t define your own primitives.

Objects

Plain objects (type Object ) can be created by object literals : { firstName: 'Jane', lastName: 'Doe' } The above object has two properties: The value of property firstName is 'Jane' , the value of property lastName is 'Doe' .

) can be created by : The above object has two properties: The value of property is , the value of property is . Arrays (type Array ) can be created by array literals : [ 'apple', 'banana', 'cherry' ] The above array has three elements that can be accessed via numeric indices. For example, the index of 'apple' is 0.

) can be created by : The above array has three elements that can be accessed via numeric indices. For example, the index of is 0. Regular expressions (type RegExp ) can be created by regular expression literals: /^a+b+$/

Compared by reference: identities are compared, every value has its own identity. > {} === {} // two different empty objects false > var obj1 = {}; > var obj2 = obj1; > obj1 === obj2 true

identities are compared, every value has its own identity. Mutable by default. > var obj = {}; > obj.foo = 123; > obj.foo 123

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

undefined and null

undefined

null

undefined means “no value”. Uninitialized variables are undefined : > var foo; > foo undefined If you read a non-existant property, you also get undefined : > var obj = {}; // empty object > obj.foo undefined Missing parameters are undefined , too: > function f(x) { return x } > f() undefined

means “no value”. Uninitialized variables are : If you read a non-existant property, you also get : Missing parameters are , 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.).

undefined

null

if (x === undefined || x === null) { ... }

undefined

null

if (!x) { ... }

false

0

NaN

''

false

Wrapper types

Foo

Array

Foo.prototype

> [].push === Array.prototype.push true

The wrapper type of booleans is Boolean . Booleans get their methods from Boolean.prototype : > true.toString === Boolean.prototype.toString true Note that the name of the wrapper type starts with a capital B . If the type of booleans was accessible in JavaScript, it would likely be called boolean .

. Booleans get their methods from : Note that the name of the wrapper type starts with a capital . If the type of booleans was accessible in JavaScript, it would likely be called . The wrapper type of numbers is Number .

. The wrapper type of strings is String .

> Number('123') 123 > String(true) 'true'

Categorizing values via typeof and instanceof

typeof

instanceof

Several identifiers are “reserved words” – they are part of the syntax and can’t be used as variable names:Technically, the following three identifiers are not reserved words, but shouldn’t be used as variable names, either:JavaScript has all the values that we have come to expect from programming languages: booleans, numbers, strings, arrays, etc. All values in JavaScript have. Each property has a key (or name) and a value. Think fields of a record. You use the dot () operator to read a property:An example: The stringhas the propertyThe above can also be written as: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 methodon the valueJavaScript makes a somewhat arbitrary distinction between values:The main difference between the two is how they are compared: each object has a unique identity and is only equal to itself:In contrast, all primitive values encoding the same value are considered the same:The following two sections explain primitive values and objects in more detail.The following are all of the(short:):Characteristics of primitives:All non-primitive values are. The most common kinds of objects are:Characteristics of objects:All data structures (such as arrays ) are objects, but not all objects are data structures. For example: regular expressions are objects, but not a data structure.Somewhat unnecessarily, JavaScript has two “non-values”:andNormally, you should treatandequivalently, 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 bothandare considered false Warning:andare also consideredThe instances of object types(including built-in types such asand any custom types) get their methods from the object. You can verify this by reading a method without invoking it:In contrast, primitives have no types you can access in the language, so each primitive type has an associated type, a so-calledWrapper types also have instances (their instances are objects), but those are practically never used. Instead, wrapper types serve another purpose: If you call them as functions, they convert values to primitive types.There are two operators for categorizing values:is mainly used for primitive values,is used for objects.

typeof looks like this:

typeof «value»

value

> typeof true 'boolean' > typeof 'abc' 'string' > typeof {} // empty object literal 'object' > typeof [] // empty array literal 'object'

It returns a string describing the “type” of. 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.

and not . Given that (the type of functions) is a subtype of (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:

«value» instanceof «Constr»

true

value

Constr

> var b = new Bar(); // object created by constructor Bar > b instanceof Bar true > {} instanceof Object true > [] instanceof Array true > [] instanceof Object // Array is a subtype of Object true

Further reading

Booleans

true

false

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

(And), (Or). Prefix logical operator: ! (Not)

(Not) Equality operators: === !== == !=

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

Truthy and falsy

if

true

false

false

undefined , null

, Boolean: false

Number: -0 , NaN

, String: ''

true

false

true

Boolean

> Boolean(undefined) false > Boolean(0) false > Boolean(3) true

Binary logical operators

foo()

false && foo() true || foo()

And: If the first operand is falsy, return it. Otherwise, return the second operand. > NaN && 'abc' NaN > 123 && 'abc' 'abc'

Or: If the first operand is truthy, return it. Otherwise, return the second operand. > 'abc' || 123 'abc' > '' || 123 123

Equality operators

===

!==

==

!=

Further reading

Numbers

> 1 === 1.0 true

NaN (“not a number”): an error value. > Number('xyz') // 'xyz' can’t be converted to a number NaN

(“not a number”): an error value. Infinity : also mostly an error value. > 3 / 0 Infinity > Math.pow(2, 1024) // number too large Infinity Infinity is sometimes useful, because it is larger than any other number. Similarly, -Infinity is smaller than any other number.

: also mostly an error value. is sometimes useful, because it is larger than any other number. Similarly, 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 : > +0 0 > -0 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

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

It returnsifis an object that has been created by the constructor(think: class). Examples:The primitive boolean type comprises the valuesand. The following operators produce booleans:Whenever JavaScript expects a boolean value (e.g. for the condition of anstatement), any value can be used. It will be interpreted as eitheror. The following values are interpreted asAll other values are considered. Values interpreted asare called, values interpreted asare called. Useas a function to test how a value is interpreted.Binary logical operators in JavaScript are– if the first operand suffices for determining the result, the second operand is not evaluated. For example, in the following code, the functionis 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: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.All numbers in JavaScript are floating point (although most JavaScript engines internally also use integers):Special numbers:JavaScript has the following arithmetic operators The global object Math provides more arithmetic operations, via functions.

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

Further reading

Strings

\

'abc' "abc" 'Did she say "Hello"?' "Did she say \"Hello\"?" 'That\'s nice!' "That's nice!" 'Line 1

Line 2' // newline 'Backlash: \\'

> var str = 'abc'; > str[1] 'b'

length

> 'abc'.length 3

String operators

+

> var messageCount = 3; > 'You have '+messageCount+' messages' 'You have 3 messages'

+=

> var str = ''; > str += 'Multiple '; > str += 'pieces '; > str += 'are concatenated.'; > str 'Multiple pieces are concatenated.'

String methods

There is a series of 2ality blog posts on numbers, covering topics such as: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 propertycounts 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.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 theoperator:Strings have many useful methods . Examples:

> 'abc'.slice(1) // copy a substring 'bc' > 'abc'.slice(1, 2) 'b' > '\t xyz '.trim() // trim whitespace 'xyz' > 'mjölnir'.toUpperCase() 'MJÖLNIR' > 'abc'.indexOf('b') // find a string 1 > 'abc'.indexOf('x') -1

Further reading

Statements

Conditionals

if

if (myvar === 0) { // then } if (myvar === 0) { // then } else { // else } if (myvar === 0) { // then } else if (myvar === 1) { // else-if } else if (myvar === 2) { // else-if } else { // else }

switch

fruit

case

switch (fruit) { case 'banana': // ... break; case 'apple': // ... break; default: // all other cases // ... }

Loops

for

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

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

while

// Same as for loop above: var i = 0; while (i < arr.length) { console.log(arr[i]); i++; }

do-while

do { // ... } while(condition);

break leaves the loop.

leaves the loop. continue starts a new loop iteration.

Functions

function add(param1, param2) { return param1 + param2; }

add

param1

param2

> add(6, 1) 7 > add('a', 'b') 'ab'

Thestatement lets a boolean condition decide between a then clause and an (optional) else clause:In the followingstatement, the value ofdecides whichis executed.Theloop has the formatExample:Theloop continues looping over its body while its condition holds.Theloop continues looping over its body while its condition holds. As the condition follows the body, the body is always executed at least once.One way of defining a function is via aThe above code defines a functionthat has two parametersandand returns the sum of both parameters. This is how you call that function:

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

var add = function (param1, param2) { return param1 + param2; };

someOtherFunction(function (p1, p2) { ... });

Function declarations are hoisted

function foo() { bar(); // OK, bar is hoisted function bar() { ... } }

var

function foo() { bar(); // Not OK, bar is still undefined var bar = function () { // ... }; }

The special variable arguments

arguments

arguments

> function f() { return arguments } > var args = f('a', 'b', 'c'); > args.length 3 > args[0] // read element at index 0 'a'

Too many or too few arguments

toArray()

function f(x, y) { console.log(x, y); console.log(toArray(arguments)); }

arguments

> f('a', 'b', 'c') a b [ 'a', 'b', 'c' ]

undefined

> f('a') a undefined [ 'a' ] > f() undefined undefined []

Optional parameters

function pair(x, y) { x = x || 0; // (*) y = y || 0; return [ x, y ]; }

||

x

null

undefined

> pair() [ 0, 0 ] > pair(3) [ 3, 0 ] > pair(3, 5) [ 3, 5 ]

Enforcing an arity

arguments.length

function pair(x, y) { if (arguments.length !== 2) { throw new Error('Need exactly 2 arguments'); } ... }

Converting arguments to an array

arguments

length

function toArray(arrayLikeObject) { return [].slice.call(arrayLikeObject); }

Further reading

Exception handling

function throwException() { throw new Error('Problem!'); } try { throwException(); } catch (e) { console.log(e); // Error: Problem! console.log(e.stack); // non-standard, but often supported }

try

catch

try

Further reading

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

Strict mode

'use strict';

function functionInStrictMode() { 'use strict'; }

Explicit errors

f()

length

function f() { 'abc'.length = 5; }

f()

function f_strict() { 'use strict'; 'abc'.length = 5; }

> f_strict() TypeError: Cannot assign to read only property 'length' of abc

this in non-method functions

this

undefined

function f_strict() { 'use strict'; return this; } console.log(f_strict() === undefined); // true

this

window

function f() { return this; } console.log(f() === window); // true

No auto-created global variables

> function f() { foo = 5 } > f() // no error > foo 5

> function f_strict() { 'use strict'; foo2 = 4; } > f_strict() ReferenceError: foo2 is not defined

Further reading

Variable scoping and closures

var

> var x; > x = 3; > y = 4; ReferenceError: y is not defined

var

var x = 1, y = 2, z = 3;

var x = 1; var y = 2; var z = 3;

Variables are function-scoped

function foo() { var x = -3; if (x < 0) { // (*) var tmp = -x; ... } console.log(tmp); // 3 }

tmp

Variables are hoisted

function foo() { console.log(tmp); // undefined if (false) { var tmp = 3; // (*) } }

function foo() { var tmp; // declaration is hoisted console.log(tmp); if (false) { tmp = 3; // assignment stays put } }

Closures

function createIncrementor(start) { return function () { // (*) return start++; } }

start

> var inc = createIncrementor(5); > inc() 5 > inc() 6 > inc() 7

createIncrementor()

IIFE: Simulating block scoping

(function () { // open block var tmp = ...; // not a global variable }()); // close block

tmp

Inadvertent sharing via closures

A function expression produces a value and can thus be used to directly pass functions as arguments to other functions:Function declarations are, moved in their entirety to the beginning of the current scope. That allows you to refer to functions that are declared later:Note that whiledeclarations are also hoisted , assignments performed by them are not: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 variablelooks like an array, but has none of the array methods.Let’s use the following function to explore how too many or too few parameters are handled in JavaScript (functionis shown later ).Additional parameters will be ignored (except by):Missing parameters will get the valueThe following is a common pattern for assigning default values to parameters:In line (*), theoperator returnsif it is truthy (not:, etc.). Otherwise, it returns the second operand.If you want to enforce an arity, you can checkis not an array, it is only array-like : It has a propertyand 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.The most common way of exception handling is shown below.Theclause surrounds critical code, theclause is executed if an exception is thrown inside theclause. 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.Let’s look at an example where strict mode gives us an explicit error, where JavaScript otherwise fails silently: The following functiondoes something illegal, it tries to change the read-only propertythat all strings have:When you call that function, it fails silently, the assignment is simply ignored. Let’s changeso that it runs in strict mode:Now we get an error:In strict mode, the value ofin non-method function isIn non-strict mode, the value ofis the so-calledin browsers):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:In JavaScript, you must declare variables viabefore you can use them:You can declare and initialize several variables with a singlestatement: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.The scope of a variable is always the complete function (as opposed to the current block). For example:We can see that the variableis not restricted to the block starting in line (*), it exists until the end of the function.Variable declarations are: 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: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 ofis a function plus the connection to the variables of its surrounding scopes. Whatreturns is thus a closure.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 preventsfrom becoming global.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:

var result = []; for (var i=0; i < 5; i++) { result.push(function () { return i }); // (*) } console.log(result[1]()); // 5 (not 1) console.log(result[3]()); // 5 (not 3)

i

i

for (var i=0; i < 5; i++) { (function (i2) { result.push(function () { return i2 }); }(i)); // copy current i }

Further reading

Objects and inheritance

Single objects

var jane = { name: 'Jane', describe: function () { 'use strict'; return 'Person named '+this.name; } };

name

describe

> jane.name // get 'Jane' > jane.name = 'John'; // set > jane.newProperty = 'abc'; // created automatically

describe

this

> jane.describe() // call method 'Person named John' > jane.name = 'Jane'; > jane.describe() 'Person named Jane'

in

> 'newProperty' in jane true > 'foo' in jane false

undefined

> jane.newProperty !== undefined true > jane.foo !== undefined false

delete

> delete jane.newProperty true > 'newProperty' in jane false

Arbitrary property keys

> var obj = { 'not an identifier': 123 }; > obj['not an identifier'] 123 > obj['not an identifier'] = 456;

> var x = 'name'; > jane[x] 'Jane' > jane['na'+'me'] 'Jane'

Extracting methods

this

undefined

> var func = jane.describe; > func() TypeError: Cannot read property 'name' of undefined

bind()

this

> var func2 = jane.describe.bind(jane); > func2() 'Person named Jane'

Functions inside a method

this

this

forEach

var jane = { name: 'Jane', friends: [ 'Tarzan', 'Cheeta' ], logHiToFriends: function () { 'use strict'; this.friends.forEach(function (friend) { // `this` is undefined here console.log(this.name+' says hi to '+friend); }); } }

logHiToFriends

> jane.logHiToFriends() TypeError: Cannot read property 'name' of undefined

this

logHiToFriends: function () { 'use strict'; var that = this; this.friends.forEach(function (friend) { console.log(that.name+' says hi to '+friend); }); }

forEach

this

logHiToFriends: function () { 'use strict'; this.friends.forEach(function (friend) { console.log(this.name+' says hi to '+friend); }, this); }

this

Constructors: factories for objects

The value returned in line (*) is always the current value of, not the value it had when the function was created. After the loop is finished,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:Like all values , objects have properties. You could, in fact, consider an object to be a set of properties, where each property is a (key, value) pair. The key is a string, the value is any JavaScript value. So far, we have only seen properties whose keys were identifiers , because those are the only keys that the dot operator can handle. In this section, you’ll learn an additional way of accessing properties that can handle arbitrary strings as keys.In JavaScript, you can directly create objects, viaThe above object has the propertiesand. You can read (“get”) and write (“set”) properties:Function-valued properties such asare called. They useto refer to the object that was used to call them.Theoperator checks whether a property exists:If you read a property that does not exist, you get the value. Hence, the previous two checks could also be performed like this:Theoperator removes a property:A property key can be any string. So far, we have seen property keys in object literals and after the dot operator. (Roughly) you can only use them that way if they are 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:If you extract a method, it loses its connection with the object. On its own, the function is not a method, any more andhas the value(in strict mode).The solution is to use the methodthat all functions have. It creates a new function whosealways has the given value.Every function has the special variable. This is inconvenient if you nest a function inside a method, because you can’t access the method’sfrom the function. The following is an example where we callwith a function to iterate over an array:Callingproduces an error:Let’s look at two ways of fixing this. Fix #1: storein a different variable.Fix #2:has a second parameter that allows you to provide a value forFunction expressions are often used as arguments in function calls in JavaScript. Always be careful when you refer tofrom one of those function expressions.Until now, you may think that JavaScript objects aremaps 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:

// Set up instance data function Point(x, y) { this.x = x; this.y = y; } // Methods Point.prototype.dist = function () { return Math.sqrt(this.x*this.x + this.y*this.y); };

Point

Point.prototype

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

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

> var p = new Point(3, 5); > p.x 3 > p.dist() 5.830951894845301

p

Point

> p instanceof Point true > typeof p 'object'

Further reading

Arrays

Array literals

> var arr = [ 'a', 'b', 'c' ];

'a'

'b'

'c'

> arr[0] 'a' > arr[0] = 'x'; > arr [ 'x', 'b', 'c' ]

is an instance ofArrays are sequences of array elements that can be accessed via integer indices starting at zero.Array literals are handy for creating arrays:The above array has three elements: the stringsand. You can access them via integer indices:

Property length always indicates how many elements an array has.

> arr.length 3

> arr.length = 2; > arr [ 'x', 'b' ]

in

> 1 in arr // does arr have an element at index 1? true > 5 in arr // does arr have an element at index 5? false

> arr.foo = 123; > arr.foo 123

Array methods

> var arr = [ 'a', 'b', 'c' ]; > arr.slice(1, 2) // copy elements [ 'b' ] > arr.slice(1) [ 'b', 'c' ] > arr.push('x') // append an element 4 > arr [ 'a', 'b', 'c', 'x' ] > arr.pop() // remove last element 'x' > arr [ 'a', 'b', 'c' ] > arr.shift() // remove first element 'a' > arr [ 'b', 'c' ] > arr.unshift('x') // prepend an element 3 > arr [ 'x', 'b', 'c' ] > arr.indexOf('b') // find the index of an element 1 > arr.indexOf('y') -1 > arr.join('-') // all elements in a single string 'x-b-c' > arr.join('') 'xbc' > arr.join() 'x,b,c'

Iterating over arrays

forEach

map

But it can also be used to remove trailing elements from the array:Theoperator works for arrays, too.Note that arrays are objects and can thus have object properties:Arrays have many methods . A few examples:There are several array methods for iterating over elements. The two most important ones areand

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

[ 'a', 'b', 'c' ].forEach( function (elem, index) { // (*) console.log(index + '. ' + elem); });

0. a 1. b 2. c

elem

The above code produces the outputNote that the function in line (*) is free to ignore arguments. It could, for example, only have the parameter

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

> [1,2,3].map(function (x) { return x*x }) [ 1, 4, 9 ]

Further reading

Regular expressions

/^abc$/ /[A-Za-z0-9]+/

Method test(): is there a match?

> /^a+b+$/.test('aaab') true > /^a+b+$/.test('aaa') false

Method exec(): match and capture groups

> /a(b+)a/.exec('_abbba_aba_') [ 'abbba', 'bbb' ]

Method replace(): search and replace

> '<a> <bbb>'.replace(/<(.*?)>/g, '[$1]') '[a] [bbb]'

replace

/g

Further reading

Math

> Math.abs(-2) 2 > Math.pow(3, 2) // 32 9 > Math.max(2, -1, 5) 5 > Math.round(1.9) 2 > Math.cos(Math.PI) // pre-defined constant for π -1

Other functionality of the standard library

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

: 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.

: 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?

Feedback welcome