A concise and accurate JavaScript tutorial/notes written
for those entering the JavaScript world for the first time
but already have experience with other languages
These slides are not completed yet;
I may modify/add some at any time.
Jong-Shian Wu, March 2015 concisense <at> gmail.com Licensed under CC BY-NC-SA
Hello world, To my surprise, so many people (more than 10k views) have been here already in less than two days, even though this work is still unfinished. I am glad people find it helpful or interesting! :-) However, I did not realize before sharing these slides that they contained some errors and are in fact not "concise" and "accurate" for audience of beginner level as pointed out by some readers. If only it was released on GitHub Pages, issues could have been opened, and that will make it easier to be improved. But in the near future I will not have enough time to port the slides to another platform yet. Let us get started --->
When referring to
JavaScript, it means
ECMAScript 5.1
There will soon be a newer version (ES6) as of 2015
We are not talking about the browser-specific
features and things provided only by Node.js here
Here we will focus on
the language itself and
the interpreter behavior
We are not covering every detail from the ground up
about JavaScript, since that would be too boring
Here we will focus on
what makes this
language special
You can use the “JavaScript Console” REPL provided by
“Firefox Developer Tools” or “Chrome Developer Tools”
to write and test any small piece of JavaScript program.
A JavaScript Interpreter/Runtime
A variable is a named
container for a value
The name that refers to a variable
is sometime called an identifier
Definition
var x;
var y = "Hello JS!";
var z;
x
z
These red boxes are variables, and each of them has a name (identifier)
undefined
"Hello JS!"
undefined
y
Any JavaScript value can be contained within these boxes
var x;
var y = "Hello JS!";
var z;
z = false;
z = 101;
x
z
undefined
"Hello JS!"
101
y
We can assign another value to a variable later after its creation
Curly-brace blocks do not introduce
new variable scopes in JavaScript
// What is i, $, p, and q afterwards?
var i = -1;
for (var i = 0; i < 10; i += 1) {
var $ = -i;
}
if (true) {
var p = 'FOO';
} else {
var q = 'BAR';
}
// Check the next slide for an answer...
var i, $, p, q; // all undefined
i = -1;
for (i = 0; i < 10; i += 1) {
$ = -i;
}
if (true) {
p = 'FOO';
} else {
q = 'BAR';
}
// i=10, $=-9, p='FOO', q=undefined
The code in previous page
actually works like this one:
When the program runs, all variable declarations
are moved up to the top of the current scope.
Reserved Words
Some keywords can not be used as variable names:
null true false break do instanceof typeof
case else new var catch finally return void
continue for switch while debugger function
this with default if throw delete in try
class enum extends super const export import
implements let private public yield
interface package protected static
We don't need to remember them all. Just be aware of the
possible cause for some SyntaxError exceptions in our program.
A value represents the most
basic data we can deal with
Definition
A type is a set of data values,
and there are exactly 6 types
Type
value
:: {
}
v1
v2
v3
,
,
...
,
undefined
Undefined
null
Null
Boolean
true
false
Number
.33
-3.14
NaN
7e-2
011
(IEEE754 64-bit doubles)
There are 5 primitive (non-Object) types
String
""
"\n"
"Hello world!"
"哈囉。"
"\""
(Any finite ordered sequence of 16-bit unsigned integers)
'w Single Quotes'
Any value here is called a primitive value
0x101
-Infinity
And then there is the "Object" type
Object
Any value of this type is a reference to some “object”;
sometimes we would simply call such value an object
ref:0x2f4b90
"a str val"
x
y
1234
addr: 0x2f4b90
true
foo
bar
addr: 0x183da5
ref:0x48264e
ref:0x183da5
Definition
An object is a
collection of properties
A property is a
named container for a value
w/ some additional attributes
The name of a property is called a key;
thus, an object can be considered as
a collection of key-value pairs.
There are similar concepts in other programming languages,
e.g., Map, Dictionary, Associative Array, Symbol Table, Hash Table, ...
Definition
To Refer To A Value
"Hello!"
y
"test"
x
y
1234
addr: 0x2f4b91
// Value containers
var y = "Hello!";
var w = {
x: "test",
y: 1234
};
ref:0x2f4b91
w
A “variable” vs a “property” in an object
// To get the values
y; // "Hello!"
w; // (the object ref)
w.x; // "test"
w['x']; // "test"
w.y; // 1234
w["y"]; // 1234
var w = {
x: "test",
y: 1234,
z: {},
w: {},
"": "hi"
};
Object Initialiser (Object Literal)
The notation using a pair of curly braces
to initialize a new JavaScript object.
var w = new Object();
w.x = "test";
w.y = 1234;
w.z = new Object();
w.w = new Object();
w[""] = "hi";
The code on the left-hand side has exactly the
same result as the one on the right-hand side
Add/Get/Set/Remove A Property
We can dynamically modify an object after its creation
var obj = {
1 : "Hello",
"3": "Good",
x : "JavaScript",
foo: 101,
bar: true,
"" : null
};
obj["2"] = "World"; // *1 Add & Set
obj["1"]; // *2 Get -> "Hello"
obj[2]; // *3 Get -> "World"
obj[3]; // *4 Get -> "Good"
obj.foo = 202; // *5 Set
delete obj.bar; // *6 Remove
delete obj[""]; // *7 Remove
Get Property After An Object Literal
JavaScript interpreter will think that we are writing
a “code block” when we start with the “curly braces”
as a JavaScript “statement”.
We can to force it to think about “an expression”
using the grouping operator.
var w = { x: "test" };
var y = { x: "test" }.x;
w.x; // "test"
y; // "test"
{ x: "test" }.x; // SyntaxError: unexpected .
({ x: "test" }.x); // "test"
({ x: "test" }).x; // "test"
({ x: "test" })['x']; // "test"
({ x: "test" }['x']); // "test"
NOTE: Getting a property after an object
literal is not considered a good pattern
Don't Forget Any Value Of The
Object Type Is Actually A “Reference”
var x = { a: 100 };
var y = { a: 100 };
100
a
addr: 0x440892
ref:0x440892
x
100
a
addr: 0x3c980c
ref:0x3c980c
y
Similar to the “pointer” / “address” concept
in programming languages like C or C++
Don't Forget Any Value Of The
Object Type Is Actually A “Reference”
var x = { a: 100 };
var y = { a: 100 };
var z = y;
x === y; // false
y === z; // true
100
a
addr: 0x440892
x
100
a
addr: 0x3c980c
y
z
ref:0x440892
ref:0x3c980c
ref:0x3c980c
Don't Forget Any Value Of The
Object Type Is Actually A “Reference”
var x = { a: 100 };
var y = { a: 100 };
var z = y;
x === y; // false
y === z; // true
z.a = 200;
100
a
addr: 0x440892
x
200
a
addr: 0x3c980c
y
z
ref:0x440892
ref:0x3c980c
ref:0x3c980c
Don't Forget Any Value Of The
Object Type Is Actually A “Reference”
var x = { a: 100 };
var y = { a: 100 };
var z = y;
x === y; // false
y === z; // true
z.a = 200;
x.a; // 100
y.a; // 200
z.a; // 200
100
a
addr: 0x440892
x
200
a
addr: 0x3c980c
y
z
ref:0x440892
ref:0x3c980c
ref:0x3c980c
Disambiguate According To The Context
When we refer to a “Variable”, a “Property”, a “Symbol”, or
an “Identifier”, we might actually mean the concept of:
When we use the word “Object”, it might be the concept of:
Definition
A function is an object
that is callable
var a = 7;
var sayhi = function (name) {
var a = "Hello " + name;
console.log(a);
return a;
};
Function Expression
The notation using the keyword “function”
followed by an argument list and a code block
to create/initialize a JavaScript Function object
Any function in JavaScript is first-class, which can be assigned
to a variable or passed as an ordinary value to another function.
Function Invocation
A pair of parentheses invokes the preceding function;
the values of zero or more arguments are passed in.
Each time a function is called/invoked, it has its own variable scope
with local variables and arguments filled with corresponding values
var a = 7;
var sayhi = function (name) {
var a = "Hello " + name;
console.log(a);
return a;
};
sayhi("J"); // "Hello J"
a; // 7
When # of Arguments Not Matched
In JavaScript, it is OK to invoke a function
with a mismatched number of arguments.
At run time, any argument without passing a value is filled with the
“undefined” value, just like a local variable without any assignment.
var f = function (a, b) {
console.log(typeof b);
return a + b;
};
f(3); // NaN ("undefined" printed)
f(3, 4); // 7 ("number" printed)
f(3, 4, 5); // 7 ("number" printed)
Function Not Returning A Value
A function does not necessarily
need to return a value explicitly.
When that is the case, the “undefined” value is returned.
var f = function () {
return;
};
var g = function () {
};
var foo = f();
foo; // undefined
g(); // undefined
Function Expression Can Be Named
var fact = function (n) {
if (n === 0) return 1;
if (n > 0) return n * fact(n - 1); // *1
};
fact(3); // 6, which is the factorial of 3
var fact2 = fact;
fact = null; // But if the value changes...
fact2(3); // TypeError: “null” is not function
var f = function fib(n) {
if (n === 0) return 0;
if (n === 1) return 1;
if (n > 1) return fib(n - 1) + fib(n - 2); // *2
};
f(10); // 55
var g = f;
f = null; // If the value changes...
g(10); // 55 (still working)
The name “fib” is accessible
only inside the function itself
Function Declaration Statement (1/2)
// We can invoke a function
// before its "declaration"
//
// Please see the next slide for the reason......
var x = 100;
plusOne(x); // 101
plusOne(y); // NaN
var y = 999;
function plusOne(n) {
return n + 1;
}
This is a “function declaration”
statement that requires a “name”
Functions can be used before their function declaration statements, because...
Function Declaration Statement (2/2)
var x, y, plusOne; // Variable declarations
plusOne = function (n) { // Function declarations
return n + 1; // are also moved to the
}; // top of current scope
x = 100;
plusOne(x); // 101
plusOne(y); // NaN
y = 999;
When program runs, all function declarations
are moved up to the top of the current scope,
as well as all variable declaration statements.
When the program runs, those function declaration statements work like this:
Invoke After A Function Expression
JavaScript interpreter will think that we are writing a
“function declaration” when we start with the keyword
“function” as a JavaScript “statement”.
We can to force it to think about “an expression” using the grouping operator. In fact, any appropriate operator would
work just fine if you do not care about the return value.
(function () {
return 123;
}()); // 123
(function(){ return 'hi'; })(); // "hi"
!function(){ console.log('ya'); }(); // true
void function(){ console.log('ya'); }(); // undefined
Definition
A method is a function
as some object's property
The property which contains a value that
references to some function is called a “method.”
So is the referenced function.
// The cat object has three properties
// cat.age, cat.meow, and cat.sleep
var cat = {
age: 3,
meow: function () {}
};
cat.sleep = function () {};
// We would say that cat.meow and
// cat.sleep are "methods" of cat
Methods of An Object
When a function is invoked as a method of
some object, the this value during the function
call is (usually) bound to that object at run-time
Refer To The Object Inside A Method
var cat = {
age: 3,
meow: function () {
console.log(this.sound);
return this.age;
},
sound: 'meow~~'
};
cat.meow(); // 3 ("meow~~" is printed)
var m = cat.meow;
m(); // TypeError or undefined
Definition
A closure is a pair of
a function and an environment
for resolving free variables
When we use non-local variables...
var a = 1;
var closureFunc = function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
The Lexical Environment (1/3)
var a = 1;
var closureFunc = function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
closureFunc(); // 1
a = 100;
closureFunc(); // 100
a = 'hello';
closureFunc(); // 'hello'
When we use non-local variables...
The Lexical Environment (2/3)
The Lexical Environment (3/3)
var a = 1;
var closureFunc = function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
var anotherFunc = function () {
var a = 2;
return closureFunc();
};
anotherFunc(); // 1
The “environment” is determined at creation-time, not at run-time
Lexical scope
Dynamic scope
(not for JavaScript)
Which variable is the identifier “a” here
bound to when the function is invoked?
var getClosureFunc = function () {
var a = 1;
var closureFunc = function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
return closureFunc;
};
var a = 3;
var clsr = getClosureFunc();
clsr(); // 1
Common Way To Create A Closure (1/3)
A function that returns a closure function...
A closure is created each time
getClosureFunc returns.
var getClosureFunc = function () {
var a = 1;
return function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
};
var a = 3;
var clsr = getClosureFunc();
clsr(); // 1
A function that returns a closure function...
Common Way To Create A Closure (2/3)
A closure is created each time
getClosureFunc returns.
var clsr = (function () {
var a = 1;
return function () {
// The "environment" (the outer scope)
// determines to which value does the
// symbol `a` resolve here
console.log(a);
return a;
};
}());
var a = 3;
clsr(); // 1
A function that returns a closure function... gets invoked immediately
Common Way To Create A Closure (3/3)
A closure is created when the
anonymous function returns.
How a variable/identifier/symbol inside a function will be
resolved for all function calls in the future is completely
determined at the creation-time of the function already
except for “this”.
JavaScript Uses Static/Lexical Scope Model
Lifetime of A Lexical Scope/Environment
The lifetime of the local variables (the environment/scope) does
not necessarily end as the function returns. If there is any local variable referenced by a returned function, a closure is created.
Only the returned functions can access those hidden private states.
var x = 999;
var f = function () {
var x = 222; // *1
return function () {
x += 100;
return x; // *2
};
};
var g = f(); // *3
g(); // 322 // *4
g(); // 422 // *5
Rethinking Named Function Expressions
A named function expression creates a closure
with the free variable of that name bound to the function itself.
var f = function fac(n) {
if (n === 0) return 1;
if (n > 0) return n * fac(n - 1);
};
//----- The above code works like: -----
var f = (function () {
var fac = function (n) {
if (n === 0) return 1;
if (n > 0) return n * fac(n - 1);
};
return fac;
}());
var w = [
"test",
1234,
{},
[],
"hi"
];
w[4]; // "hi"
Array Initialiser (Array Literal)
The notation using a pair of square brackets
to create/initialize a JavaScript Array object.
var w = new Array(5);
w[0] = "test";
w[1] = 1234;
w[2] = new Object();
w[3] = new Array();
w[4] = "hi";
w[4]; // "hi"
The code on the left-hand side has exactly the
same result as the one on the right-hand side
Append New Elements To An Array
var arr = [ "test", 1234, {}, [], "hi" ];
arr.push("sixth"); // 6
arr.length; // 6
arr[5]; // "sixth"
arr[7] = 012; // 10
arr.length; // 8
arr[6]; // undefined
arr[7]; // 10
arr[8]; // undefined
arr.length; // 8
There is a method “push” for all Array objects.
Or you can just assign a value to the corresponding slot.
Enumerate All Elements In An Array (1/3)
var arr = [ "test", 1234, {}, [], "hi" ];
for (var i = 0; i < arr.length; i += 1) {
console.log(arr[i]);
}
There is a special property “length” for any Array object.
NOTE: A “For-loop” is not always recommanded
for enumerating all elements in an array, because...
Enumerate All Elements In An Array (2/3)
var arr = [ "test", 1234, {}, [], "hi" ];
arr.forEach(function (val /*, i, arr*/) {
console.log(val);
});
// undefined
There is a special method “forEach” for any Array object.
The “forEach” method is much nicer...
Enumerate All Elements In An Array (3/3)
var arr = [ "test", 1234, {}, [], "hi" ];
arr.map(function (val /*, i, arr*/) {
return typeof val;
});
// [ "string",
// "number",
// "object",
// "object",
// "string" ]
There is a special method “map” for any Array object.
We even have functional “map”, “every”, “some”, ... See the notes for more info
Calling Object.keys( ... ) gives you all enumerable “keys” in an object
How You Can Enumerate An “Object” (1/2)
var obj = { a: "test", b: 1234, c: "hi" };
Object.keys(obj); // [ "a", "b", "c" ]
Calling Object.keys( ... ) with map gives you all enumerable “values”
How You Can Enumerate An “Object” (2/2)
var obj = { a: "test", b: 1234, c: "hi" };
Object.keys(obj).map(function (key) {
return obj[key];
});
// [ "test",
// 1234,
// "hi" ]
Review The Data Types We've Seen So Far
Undefined
Null
Boolean
Number
String
Object
There are exactly 6 types
of values in JavaScript
Review The Data Types We've Seen So Far
Undefined
Null
Boolean
Number
String
Object
These 2 are pretty boring
Review The Data Types We've Seen So Far
Undefined
Null
Boolean
Number
String
Object
These 3 are more useful primitives
Review The Data Types We've Seen So Far
Undefined
Null
Boolean
Number
String
Object
This is the most interesting data type
where we can start having nested and
organized program structures
“Object” Type Can Be Further Categorized
Function
Object
Array
Object
Undefined
Null
Boolean
Number
String
In Fact There Are More Categories
Function
Object
Array
Undefined
Null
Boolean
Number
String
Object
Boolean
Number
String
Date
RegExp
Error
......
What are these 3 categories of... objects?
( true ).toString(); // "true"
( false ).toString(); // "false"
( 3.14 ).toString(); // "3.14"
( 3.14 ).toFixed(); // "3"
( "Hello" ).length; // 5
( "Hello" ).toUpperCase(); // "HELLO"
( "HELLO" ).slice(1, -1); // "ELL"
( "Hello world" ).split("o"); // [ "Hell", " w", "rld" ]
Where do those properties and methods come?
Let's play with some primitive values...
Note: Check the code snippets for more about “String” values
These 3 Are Used By ToObject Conversion
Undefined
Null
Boolean
Number
String
Object
Function
Object
Array
Boolean
Number
String
Date
RegExp
Error
Since there are wrapper objects for the 3 types of primitive values,
a Boolean/Number/String primitive value can behave like an object
......
There Is A “Constructor” For Each Category
Function
Object
Array
Undefined
Null
Boolean
Number
String
Object
Boolean
Number
String
Date
RegExp
Error
By the new operator or some object initialiser/literal notations,
we construct a new object of that “category” using the constructor.
......
Definition
A constructor is a function that
has a property named “prototype”
which can be used to implement
inheritance and shared properties
The value for the “prototype”
property is either null or an object
Let's take a look at
how an object is created
As an example, assume that we want to have
a new object instance of the “Array” category...
Array.prototype.length; // 0
Array.prototype.map; // fx
Array.prototype.toString; // fx
Array.prototype.forEach; // fx
Array.prototype.filter; // fx
Array.prototype.indexOf; // fx
ref:0x693e0c
map
toString
addr: 0x2f4b91
ref:0x2f3668
Array
ref:0x069db8
"Array"
name
prototype
addr: 0x069db8
ref:0x2f4b91
. . .
...
. . .
...
This is the “Array” constructor
This is the “Array.prototype” object
0
length
The built-in “Array” constructor/function/object is used
to construct a new array, and the object “Array.prototype” already contains many useful properties by default.
addr: 0x2f4b91
Array
ref:0x069db8
"Array"
name
prototype
addr: 0x069db8
ref:0x2f4b91
. . .
...
2
length
addr: 0x012345
This is the “Array” constructor
an instance of “Array”
ref:0x693e0c
map
toString
ref:0x2f3668
. . .
...
This is the “Array.prototype” object
0
length
[,,]; // or:
new Array(2);
When an “initialiser” or “new” occurs, an object is created
with some properties depending on the constructor.
For example, the “length” property is set by “Array”.
addr: 0x2f4b91
Array
ref:0x069db8
"Array"
name
prototype
addr: 0x069db8
ref:0x2f4b91
. . .
...
2
length
[[Prototype]]
addr: 0x012345
ref:0x2f4b91
This is the “Array” constructor
an instance of “Array”
ref:0x693e0c
map
toString
ref:0x2f3668
. . .
...
This is the “Array.prototype” object
0
length
[,,]; // or:
new Array(2);
Then, something called “the prototype” of the object
is set to whatever “Array.prototype” is. Here we denote
it as an internal property named “[[Prototype]]”.
var arr = [,,]; // or:
var arr = new Array(2);
addr: 0x2f4b91
Array
ref:0x069db8
"Array"
name
prototype
addr: 0x069db8
ref:0x2f4b91
. . .
...
arr
ref:0x012345
2
length
addr: 0x012345
ref:0x2f4b91
This is the “Array” constructor
This is the object “arr”,
an instance of “Array”
ref:0x693e0c
map
toString
ref:0x2f3668
. . .
...
This is the “Array.prototype” object
0
length
[[Prototype]]
Every JavaScript object has an
internal [[Prototype]] property
(usually) with the same value
as its constructor's “prototype”
property
Remark
We will use “X's prototype” to
refer to the object or a null value
referenced by the internal
[[Prototype]] property of “X”
Remark
An object can inherit properties from its prototype
Object Properties & The Prototype Chain
To get the value of the property named X in the object Y:
Step 1: If Y contains a property named X,
the value of that property is returned.
Step 2: Otherwise, if Y's prototype is null, return undefined;
else, return the value of the property named X in Y's prototype.
To set the value of the property named X in the object Y to Z:
Step 1: If Y contains no property named X, create one.
Step 2: Assign Z to that property named X in Y.
An “own property” is a property
that is directly contained by its object
Definition
An “inherited property” is a property
of an object that is not an own property
but is a property (own or inherited) of the object's prototype
var arr = [ 11, 22 ];
arr.length; // 2
arr.toString(); // "11,22"
arr.map(function(n){return n+1}); // [ 12, 23 ]
arr.hasOwnProperty('length'); // true
arr.hasOwnProperty('toString'); // false
arr.hasOwnProperty('map'); // false
Array.prototype.hasOwnProperty('toString'); // true
Array.prototype.hasOwnProperty('map'); // true
Array Constructor As An Example
For the object arr, “length” is an own property, but “toString” and “map” are not.
var Cat = function (name) {
if (name) this.name = name;
};
Cat.prototype.name = 'Nyan Cat';
Cat.prototype.meow = function () {
return 'Meow~ I am ' + this.name;
};
var pusheen = new Cat('Pusheen the cat');
var nyancat = new Cat; // () can be omitted when no args
pusheen.meow(); // "Meow~ I am Pusheen the cat"
nyancat.meow(); // "Meow~ I am Nyan Cat"
Custom Constructor Function
Note the identifier “this” is bound to the newly created object
when a function is called as a constructor using the new operator.
var catPrototype = {
name: 'Nyan Cat',
meow: function () {
return 'Meow~ I am ' + this.name;
}
};
var pusheen = Object.create(catPrototype);
pusheen.name = 'Pusheen the cat';
var nyancat = Object.create(catPrototype);
pusheen.meow(); // "Meow~ I am Pusheen the cat"
nyancat.meow(); // "Meow~ I am Nyan Cat"
An Easier Way To Create New Objects
We can create new objects “with specified prototypes” directly
How Do We Code With All Those Objects?
“The global object” stores all ECMAScript standard built-in objects/values as well as any object provided by the host.
Each global variable is stored in “the global object” as a property with the corresponding name and value.
For example, the constructors we mentioned previously, e.g., Object, Function, Array, String, Date, RegExp, are all properties of the global object. Most of the host provided APIs like “setTimeout” and “XMLHttpRequest” are also properties of the global object.
What Is “The Global Object” For?
We can refer to “the global object”...
by “this” in the global scope when not in “strict” mode,
by the global variable “window” in a web browser, or
by the global variable “global” in the Node.js runtime.
We can refer to an existing “property” of the global object...
by writing an identifier of that property name directly
when no variable has the same name inside the current
scope chain.
Check MDN reference for a list of standard global variables.
Access The Global Object & Its Properties
Most of the syntax in JavaScript is the same as
in programming languages like C, C++, and Java
Refer to MDN Reference when you encounter any problem
If you want to kill some time, here is a
quiz with 8 questions for you to take
Those questions are expected to be finished under 1.5 hours.
Of course you can keep these slides or
any other online resources as reference.
These slides cover the most fundamental concepts we will
commonly use in JavaScript that are different from other
popular languages like C, C++, Java, Python, and Ruby.
Now you can learn how to write a JavaScript
program that lives in an HTML Web page
to interact with the user of a Web browser.
You can also start learning how to write
a Web server that can respond to HTTP
requests programmatically using “Node.js”.