
Yeah, JavaScript!

Because Forrest Gump is one of those movies ...
... and because Robert Nyman made an awesome presentation about it, which formed the starting point for these slides.
Another thank you goes out to Mathias Bynens (2nd one from the left) who gave some handy remarks.

Life is like a box of chocolates,
you never know what you're gonna get
firstName and firstname are not the same!3 will be a number"Hello" it'll become a stringvar keyword and assign a value to a name
var firstName = 'Forrest';
alert(firstName);
// Dynamic typing
var firstName = 'Forrest';
alert(typeof firstName); // string
// Weak typing
firstName = 3;
alert(typeof firstName); // JavaScript has changed the type to number
var firstName = 'Forrest',
lastName = 'Gump';
alert(firstName);
alert(lastName);
stringnumber
booleannull
undefined
Array? And Date? And ...?
Objects reallystring you also have something like String
Object
Let me explain on the next few slides ;)
Object
Object is the core of the languageString, Number, Boolean, Array, etc.
ObjectmyString.length; (Also noted as String#length)myString.toUpperCase(); (Also noted as String#toUpperCase)var firstName = new String('Forrest');
Stringobjectstringvar firstName = new String('Forrest');
alert(firstName instanceof String); // true
alert(typeof firstName); // object
alert(typeof firstName.toString()); // string
var firstName = 'Forrest';
string (dynamic typing in action)var firstName = 'Forrest';
alert(firstName instanceof String); // false
alert(typeof firstName); // string

It's not that hard, really!
Integer num = new Integer(3); // Not Literal
Integer num = 3; // Literal
StringNumberBooleanRegExpFunction (*)ArrayObjectvar firstName = new String('Forrest'); // String Constructor
var firstName = 'Forrest'; // String Literal
var birthYear = new Number('1945'); // Number Constructor
var birthYear = 1945; // Number Literal
var isRunning = new Boolean('false'); // Boolean Constructor
var isRunning = false; // Boolean Literal
var hasR = new RegExp('r', 'i'); // RegExp Constructor
var hasR = /r/i; // RegExp Literal
var says = new Function('sentence', 'alert(sentence)'); // Function Constructor
var says = function(sentence) { alert(sentence); }; // Function Literal
function says(sentence) { alert(sentence); }; // The function statement
var forrestFriends = new Array('Bubba', 'Lieutenant Dan');
var forrestFriends = ['Bubba', 'Lieutenant Dan']; // Array Literal
var forrest = new Object();
forrest.firstName = 'Forrest';
forrest.lastName = 'Gump';
var forrest = { // Object Literal
firstName : 'Forrest', // semi-colons to assign
lastName : 'Gump',
says : function() { // works with functions too!
return 'Stupid is as stupid does';
} // no trailing comma (!)
};
string, number, boolean), you'll get the primitive returned when using the literal notation!
// String Instance
var lastName = new String('Gump');
alert(typeof lastName); // object
alert(lastName instanceof String); // true
// String Literal
var firstName = 'Forrest';
alert(typeof firstName); // string
alert(firstName instanceof String); // false
Object, Array, RegExp, Function), the literal will return an instance when using the literal notation.
// Array Instance
var forrestFriends = new Array('Bubba', 'Lieutenant Dan');
alert(typeof forrestFriends); // object
alert(forrestFriends instanceof Array); // true
// Array Literal
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
alert(typeof forrestFriends); // object
alert(forrestFriends instanceof Array); // true

Or at least I hope you do
String) derive from Object?
// Number Instance
var birthYear = new Number('1945');
alert(typeof birthYear);
alert(birthYear instanceof Number);
alert(birthYear instanceof Object);
// Array Instance
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
alert(typeof forrestFriends);
alert(forrestFriends instanceof Array);
alert(forrestFriends instanceof Object);
// Function literal
var says = function() { alert('Stupid is as stupid does'); };
alert(typeof says); // <-- the odd one out
alert(says instanceof Function);
alert(says instanceof Object);

Now, back to variables
// Object Literal
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
sentence : 'Stupid is as stupid does',
says : function() {
return this.sentence;
}
};
// test
console.log(forrest);
alert(forrest.firstName);
alert(forrest['firstName']);
alert(forrest.says());
// Various 'false' values
var nullVal = null;
var undefinedVal = undefined;
var zeroVal = 0;
var falseVal = false;
var emptyString = '';
if (emptyString) {
alert('truthy');
} else {
alert('falsy'); // false-ish
}
console.log('5' + 6 + 7);
// Equality
alert((7 == '7') ? 'equal' : 'not equal');
// Identity
alert((7 === '7') ? 'equal (identity)' : 'not equal (identity)');
// Type Coercion (default)
alert('5' + 6 + 7);
// Prevent Type Coercion
alert(parseInt('5', 10) + 6 + 7);
// Global
var quote = 'I had run for 3 years, 2 months, 14 days, and 16 hours.';
var foo = function() {
var saying = 'My name is Forrest, Forrest Gump'; // Local
alert(saying);
alert(quote); // Access to Global
question = 'Why don\'t you love me, Jenny?'; // Local ?
alert(question);
};
foo();
alert(quote);
// alert(saying); // disabled, will fail
alert(question); // Nope, Chuck Testa! Erm, I mean global!
var keyword is mandatory.
var keyword inside functions, loops, etc.
String#lengthString#toUpperCaseArray#isArray// String Instance
var firstName = new String('Forrest'); // an instance of String
alert(firstName.toUpperCase());
// String Literal
var firstName = 'Forrest'; // a variable of the type string
alert(firstName.toUpperCase());
// Look ma, no var
alert('Forrest'.toUpperCase());
alert(['Bubba', 'Lieutenant Dan'].length);
Object
String, Number, Boolean)

I had run for 3 years, 2 months, 14 days, and 16 hours.
// If statement
var badGrades = true;
if (badGrades) {
alert('Mom sleeps with teacher');
} else {
alert('Mom does not sleep with teacher');
}
// Switch statement
var age = 10,
lifeState;
switch (age) {
case 10:
lifeState = 'Young';
break;
case 60:
lifeState = 'Old';
break;
default:
lifeState = 'unknown';
break;
}
alert(lifeState);
// Var we'll be using
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
// For
for (var i = 0; i < forrestFriends.length; i++) {
alert(forrestFriends[i]);
}
Performance can be improved by caching variables. That way JavaScript doesn't have to look up everything again.
// Var we'll be using
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
// For
for (var i = 0, len = forrestFriends.length; i < len; i++) {
alert(forrestFriends[i]);
}
// Vars we'll be using
var forrest = {
firstName : 'Forrest',
lastName : 'Gump' // no trailing comma (!)
};
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
// For - In (Array)
for (var friend in forrestFriends) {
alert(forrestFriends[friend]);
}
// For - In (Object)
for (var prop in forrest) {
alert(prop + ' = ' + forrest[prop]);
}
Note: When using arrays, the order is not guaranteed! Better to use Array#forEach
// While
var count = 5;
while (count > 0) {
console.log(count);
count--;
}
// Do - While
var count = 5;
do {
console.log(count);
count--;
} while (count > 0);
// Tip: retry this example with count = 0 as starting value
// Vars we'll be using
var forrest = {
firstName : 'Forrest',
lastName : 'Gump' // no trailing comma (!)
};
// With
with (forrest) {
alert(firstName);
alert(lastName);
}
Note: With is considered harmful and performs badly. Not suggested.
// Vars we'll be using
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
console.log('Stupid is as stupid does');
}
};
// Try-Catch
try {
forrest.functionDoesNotExist();
} catch (error) {
console.error('ERROR! ' + error.name + ' : ' + error.message);
}
// Try-Catch-Finally
try {
forrest.functionDoesNotExist();
} catch (error) {
console.error('ERROR! ' + error.name + ' : ' + error.message);
} finally {
forrest.says();
}
Not a real control structure, but found it fitting here
switch, for, for-in, while, and do-while
for (var x = 1; x <= 5; x++) {
var y = 1;
while (y <= 7) {
if (y == 5) { break; }
console.log(x + '-' + y);
y++;
}
}
myForLoop:
for (var x = 1; x <= 5; x++) {
var y = 1;
while (y <= 7) {
if (y == 5) { break myForLoop; }
console.log(x + '-' + y);
y++;
}
}
for, for-in, while, and do-while
for (var x = 1; x <= 5; x++) {
for (var y = 1; y <= 7; y++) {
if (y == 5) continue;
console.log(x + '-' + y);
}
}
myForLoop:
for (var x = 1; x <= 5; x++) {
for (var y = 1; y <= 7; y++) {
if (y == 5) { continue myForLoop; }
console.log(x + '-' + y);
}
}
In this example you get the same result as the first break example

My name is Forrest, Forrest Gump.
// A var we'll need
var looking = true;
// How you'd probably write it at first
var forrestSays;
if (looking) {
forrestSays = 'I gotta find Bubba!';
} else {
forrestSays = 'It\'s OK';
}
alert(forrestSays);
// A var we'll need
var looking = true;
// Better: Ternary operators
var forrestSays = looking ? 'I gotta find Bubba!' : 'It\'s OK';
alert(forrestSays);
// How you'd probably write it at first
var lifeIs = function(boxOfChocolates) {
var life;
if (!boxOfChocolates) {
life = 'a Snickers bar';
} else {
life = boxOfChocolates;
}
return 'Life is like ' + life;
};
alert(lifeIs('a Box of Chocolates'));
// Better: Shorthand assignment
var lifeIs = function(boxOfChocolates) {
return 'Life is like ' + (boxOfChocolates || 'a Snickers bar');
};
alert(lifeIs('a Box of Chocolates'));
// An Object we'll need
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
alert('Stupid is as stupid does');
}
};
// How you'd probably write it at first
if ((forrest != null) && (forrest.says != null)) {
forrest.says();
}
// An Object we'll need
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
alert('Stupid is as stupid does');
}
};
// Short circuit logic
forrest && forrest.says && forrest.says();
var example = 'Forrest'.substr(0,5).split('').join('-').toUpperCase();
alert(example);

Run Forrest, Run()
// Function Constructor
var says = new Function('sentence', 'alert(sentence)');
// function statement or function declaration
function says(sentence) { alert(sentence); };
// function expression or function operator
var says = function(sentence) { alert(sentence); };
var says = function(sentence) {
alert(sentence);
};
says('Stupid is as stupid does');
var says = function(sentence) {
alert(sentence);
};
var forrestSays = function(whatForrestSays) {
says('Forrest Says "' + whatForrestSays + '"');
};
forrestSays('Stupid is as stupid does');
var change = function(obj) {
obj.sentence = 'My name is Forrest, Forrest Gump';
};
// Object Literal => Object Returned
var forrest = {
sentence : 'Stupid is as stupid does'
};
alert(forrest.sentence);
change(forrest);
alert(forrest.sentence);
var change = function(arr) {
arr.unshift('Jenny');
};
// Array Literal => Array (essentially Object) Returned
var forrestFriends = ['Bubba', 'Lieutenant Dan'];
alert(forrestFriends.length);
change(forrestFriends);
alert(forrestFriends.length);
var change = function(sentence) {
sentence = 'My name is Forrest, Forrest Gump';
};
var sentence = 'Stupid is as stupid does'; // String literal (string)
alert(sentence);
change(sentence);
alert(sentence);
var change = function(sentence) {
sentence = 'My name is Forrest, Forrest Gump';
};
var sentence = new String('Stupid is as stupid does'); // String Instance (Object)
alert(sentence);
change(sentence);
alert(sentence);
var logs = function(sentence) {
console.log(sentence);
};
var says = function(sentence) {
alert(sentence);
};
var forrestDoes = function(fn, sentence) {
fn(sentence);
};
forrestDoes(says, 'Stupid is as stupid does');
forrestDoes(logs, 'Stupid is as stupid does');
fn with the actual passed in function
Function#toString
var logs = function(sentence) {
console.log(sentence);
};
var says = function(sentence) {
alert(sentence);
};
var forrestDoes = function(fn, sentence) {
alert(fn.toString());
fn(sentence);
};
forrestDoes(says, 'Stupid is as stupid does');
forrestDoes(logs, 'Stupid is as stupid does');
var forrestDoes = function(fn, sentence) {
fn(sentence);
};
forrestDoes(function(sentence) { // says from the previous example
alert(sentence);
}, 'Stupid is as stupid does');
forrestDoes(function(sentence) { // logs from the previous example
console.log(sentence);
}, 'Stupid is as stupid does');
function change(fn) {
fn = function() {
alert('changed');
};
};
var says = function() {
alert('Stupid is as stupid does');
};
says();
change(says);
says();
var says = function() { };
alert(typeof says); // Not an object!
var forrest = {
sentence : 'Stupid is as stupid does',
say : function() {
return this.sentence;
}
};
var show = function(fn) {
alert(fn());
};
show(forrest.say);
this has hanged!var forrest = {
sentence : 'Stupid is as stupid does',
say : function() {
return this.sentence;
}
};
var show = function(obj) {
alert(obj.say());
};
show(forrest);
Function#call
var forrest = {
sentence : 'Stupid is as stupid does',
say : function() {
return this.sentence;
}
};
var show = function(obj, fn) {
alert(fn.call(obj));
};
show(forrest, forrest.say);
Function#call lets you call a function and give a new meaning to this when calling itFunction#call later
var run = function() {
alert('Run Forrest, Run');
};
run();
var run = (function() {
alert('Run Forrest, Run');
});
run();
run();, JavaScript will replace the run part of that statement with the actual contents of the variable run
(function() {
alert('Run Forrest, Run');
})();
(function() {
alert('Run Forrest, Run');
}()); // The Crockford Way
(function(sentence) {
alert(sentence);
})('Run Forrest, Run');
run('Run Forrest, Run');
var toSay = 'Run Forrest, Run';
(function(sentence) {
alert(sentence);
})(toSay);
var forrestSays = function(whatForrestSays) {
var says = function(sentence) {
alert(sentence);
};
says(whatForrestSays);
};
forrestSays('Stupid is as stupid does');
var forrestSays = function(whatForrestSays) {
var says = function(sentence) {
alert(sentence);
};
says(whatForrestSays);
};
forrestSays('Stupid is as stupid does');
says('Stupid is as stupid does'); // will fail, not in scope!
var says = function(sentence) {
alert('Outer says, says "' + sentence + '"');
};
var forrestSays = function(whatForrestSays) {
var says = function(sentence) {
alert('Inner says, says "' + sentence + '"');
};
says(whatForrestSays);
};
forrestSays('Stupid is as stupid does');
says('Stupid is as stupid does'); // won't fail
says from within forrestSays?return statement
var says = function(what, verb) {
return what + ' ' + verb;
};
var shitHappens = says('Shit', 'happens');
alert(shitHappens);
var says = function(what) {
return function(verb) {
return what + ' ' + verb;
};
};
var shit = says('Shit');
alert(shit('happens'));
// also possible
alert(says('Shit')('happens'));
LexicalEnvironment)
Yeah, I understand ... lets just check an example
var firstName = 'Forrest';
var forrestFriends = function() {
var friends = ['Bubba', 'Lieutenant Dan'];
var friendsCount = function() {
return friends.length;
};
var joinFriends = function() {
return firstName + ' has ' + friendsCount() + ' friends: ' + friends.join(', ');
};
return joinFriends();
};
alert(forrestFriends());
joinFriends (or any of the other functions) is created, a closure is created
var firstName = 'Forrest';
var forrestFriends = function() {
var friends = ['Bubba', 'Lieutenant Dan'];
var friendsCount = function() {
return friends.length;
};
var joinFriends = function() {
return firstName + ' has ' + friendsCount() + ' friends: ' + friends.join(', ');
};
return joinFriends();
};
alert(forrestFriends());
joinFriends is everything “on the same level of it”, thus everything inside the curly brackets of forrestFriends
LexicalEnvironment of the created closure holds the variablesfriends, friendsCount and joinFriends
var firstName = 'Forrest';
var forrestFriends = function() {
var friends = ['Bubba', 'Lieutenant Dan'];
var friendsCount = function() {
return friends.length;
};
var joinFriends = function() {
return firstName + ' has ' + friendsCount() + ' friends: ' + friends.join(', ');
};
return joinFriends();
};
alert(forrestFriends());
firstName? That wasn't part of the current scope?
LexicalEnvironment, it will try the outer LexicalEnvironment (go up one level) to (hope to) find it there
LexicalEnvironment of the closure created when forrestFriends was created; which has access to the vars in the global scope

Please, bear with me, there are some facts you should know
LexicalEnvironment
var firstName = 'Forrest';
var forrestFriends = function() {
var friends = ['Bubba', 'Lieutenant Dan'];
var friendsCount = function() {
return friends.length;
};
var joinFriends = function() {
return firstName + ' has ' + friendsCount() + ' friends: ' + friends.join(', ');
};
friends.unshift('Jenny'); // Change friends, after the function was created
return joinFriends();
};
alert(forrestFriends());
var firstName = 'Forrest';
var forrestFriends = function() {
var friends = ['Bubba', 'Lieutenant Dan'];
var friendsCount = function() {
return friends.length;
};
var joinFriends = function() {
return firstName + ' has ' + friendsCount() + ' friends: ' + friends.join(', ');
};
return joinFriends;
};
var ff = forrestFriends();
// at this moment, the outer function has ended
// only joinFriends() was returned
// what about friends and friendsCount? Will they still exist?
alert(ff());
var add = function(x) {
return function(y) {
return x + y;
};
};
var add5 = add(5),
add6 = add(6);
var eleven = add5(6),
twelve = add6(6);
alert(eleven);
alert(twelve)
add5 has become
function(y) {
return x + y;
}; // How I know? Try alert(add5.toString()); in the example above ;)
x?
LexicalEnvironment)var sum = function(a, b, c, d, e) {
return a + b + c + d + e
};
alert(sum(1,2)); // NaN (!)
alert(sum(1,2,3,4,5)); // 15
alert(sum(1,2,3,4,5,6)); // What now?
arguments variable inside each function
var sum = function() {
alert(typeof arguments);
alert(arguments instanceof Object);
alert(arguments instanceof Array);
};
sum(1,2);
arguments variable is an Object, and not an Array, as you can see!Object with a for loop just as you'd do with an Array
var sum = function() {
var sum = 0;
for (var i = 0, len = arguments.length; i < len; i++) {
sum += parseInt(arguments[i]);
}
return sum;
};
alert(sum(1,2));
alert(sum(1,2,3,4,5));
alert(sum(1,2,3,4,5,6));
arguments to an other function?
var otherFunc=function() {
alert('otherFunc : ' + arguments.length);
};
var myFunc = function() {
alert('myFunc : ' + arguments.length);
otherFunc(arguments);
};
myFunc(1,2,3,4,5,6,7,8,9,10);
Function#apply and Function#call
Function#apply allows you to call an other function and give it a new meaning of this. Arguments passed in using an Array-like Object
Function#apply(this, Array(arg1[, arg2[, ...[, argN]]]));
var otherFunc = function() {
alert('otherFunc : ' + arguments.length);
};
var myFunc = function() {
alert('myFunc : ' + arguments.length);
otherFunc.apply(this, arguments);
};
myFunc(1,2,3,4,5,6,7,8,9,10);
this laterFunction#call does the same as Function#apply, but passed in arguments must be passed in one by one (comma separated)
Function#call(this, arg1[, arg2[, ...[, argN]]]);
Function#apply in this context though, as we can immediately pass in arguments or any other Array or Object
Function#bind also exists, but we'll touch that later
var says = function() {
var firstName = arguments[0],
sentence = arguments[1];
return firstName + ' says "' + sentence + '"';
};
alert(says('Forrest', 'Stupid is as stupid does'));
0 is who and index 1 is what in this example
Object
var says = function(person) {
return person.firstName + ' says "' + person.sentence + '"';
};
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
sentence : 'Stupid is as stupid does',
birthYear : 1945
};
alert(says(forrest));
var extend = function(params, defaults) {
for (var i in defaults) {
if (!params[i]) {
params[i] = defaults[i];
}
}
};
var foo = function(params) {
var defaults = { position: 'left', start: 0, stop: 10 };
extend(params, defaults);
console.log(params);
};
foo({ position: 'left', start: 3 });
LexicalEnvironmentarguments or pass in your own Object

Gump! What's your sole purpose in this army?
To do whatever you tell me, drill sergeant!
Object
// Object Constructor
var forrest = new Object();
forrest.firstName = 'Forrest';
forrest.lastName = 'Gump';
forrest.says = function() {
return 'Stupid is as stupid does';
};
alert(forrest.says());
// Object Literal
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
return 'Stupid is as stupid does';
} // no trailing comma (!)
};
alert(forrest.says());
this keyword
// Object Literal
var forrest = {
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
return this.firstName + ' says "Stupid is as stupid does"';
}
};
alert(forrest.says());
this?Function#call or Function#apply, this will be set to the first argument passed to call/apply. If the first argument passed to call/apply is null or undefined, this will refer to the global object.Function#bind, this will be the first argument that was passed to bind at the time the function was created.this will refer to that object.Object
var forrest = { // Forrest
firstName : 'Forrest',
lastName : 'Gump',
says : function() {
return this.firstName + ' says "Stupid is as stupid does"';
}
};
var dan = { // Lieutenant Dan
firstName : 'Dan',
lastName : 'Taylor',
says : function() {
return this.firstName + ' says "I\'m here to try out my sea legs"';
}
};
// Jenny
// ...
var Person = function(firstName, lastName, sentence) {
this.firstName = firstName;
this.lastName = lastName;
this.sentence = sentence;
this.says = function() {
return this.firstName + ' says "' + this.sentence + '"';
};
};
var forrest = new Person('Forrest', 'Gump', 'Stupid is as stupid does');
var dan = new Person('Dan', 'Taylor', 'I\'m here to try out my sea legs');
alert(forrest.says());
alert(dan.says());
Person#firstName, Person#lastName, Person#sentence and Person#says as those are properties/methods of PersonPerson#firstName and the others in the .prototype of Person
Person#firstName, we actually say Person.prototype.firstName
.prototype, you're basically changing the class definition
.prototype
console.log(String.prototype);
.prototype, you're basically changing the class definition
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Person.prototype.isRunning = false;
Person.prototype.run = function() {
this.isRunning = true;
};
var forrest = new Person('Forrest', 'Gump');
var dan = new Person('Dan', 'Taylor');
alert(forrest.isRunning ? 'Forrest is running' : 'Forrest is not running');
alert(dan.isRunning ? 'Dan is running' : 'Dan is not running');
forrest.run();
alert(forrest.isRunning ? 'Forrest is running' : 'Forrest is not running');
alert(dan.isRunning ? 'Dan is running' : 'Dan is not running');
Number.prototype.fahrenheitToCelcius = function() {
return (parseInt(this, 10) - 32) / 1.8;
};
Number.prototype.celciusToFahrenheit = function() {
return (parseInt(this, 10) * 1.8) + 32;
};
var c = 40;
var f = 104;
alert(c.celciusToFahrenheit());
alert(f.fahrenheitToCelcius());
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Person.prototype.fullName = function() {
return this.firstName + ' ' + this.lastName;
};
var Actor = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Actor.prototype = new Person; // Inheritance
var forrest = new Person('Forrest', 'Gump');
var tomhanks = new Actor('Tom', 'Hanks');
alert(forrest.fullName());
alert(tomhanks.fullName());
Function#call
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Person.prototype.fullName = function() {
return this.firstName + ' ' + this.lastName;
};
var Actor = function(firstName, lastName) {
Person.call(this, firstName, lastName);
};
Actor.prototype = new Person;
var forrest = new Person('Forrest', 'Gump');
var tomhanks = new Actor('Tom', 'Hanks');
alert(forrest.fullName());
alert(tomhanks.fullName());
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
var Actor = function(firstName, lastName) {
Person.call(this, firstName, lastName);
};
Actor.prototype = new Person;
Person.prototype.isHuman = true;
var forrest = new Person('Forrest', 'Gump');
var tomhanks = new Actor('Tom', 'Hanks');
alert(forrest.isHuman ? 'Human' : 'Not Human');
alert(tomhanks.isHuman ? 'Human' : 'Not Human');
var forrest = (function() {
var firstName = 'Forrest'; // Private var
var says = function() { // Private function
return 'Stupid is as stupid does';
};
return {
lastName : 'Gump', // Public var
getLastName : function() { // Public function
return this.lastName; // use this when accessing a public var
},
getFirstName : function () {
return firstName; // no this when accessing private vars!
}
};
})(); // IIFE
alert(forrest.getFirstName() + ' ' + forrest.getLastName());
var forrest = (function() {
var firstName = 'Forrest';
var lastName = 'Gump';
var says = function() {
return 'Stupid is as stupid does';
};
var getLastName = function() {
return lastName;
};
var getFirstName = function () {
return firstName;
};
return {
getFirstName: getFirstName,
getLastName: getLastName,
whatDoesHeSay: says
};
})(); // IIFE
alert(forrest.whatDoesHeSay());

Stupid is as stupid does
Array#forEach is only available since JavaScript 1.6)<!DOCTYPE HTML>
<html>
<head>
<title>The document</title>
</head>
<body>
<div>Data</div>
<ul>
<li>Warning</li>
<li></li>
</ul>
<div>Top Secret!</div>
</body>
</html>
Yes, whitespace counts as a node too!
window.document offers quite a few ways of selecting elements from the document
// get one element with the given id
var el = document.getElementById('siteWrapper');
// get all links (<a> elements)
var links = document.getElementsByTagName('a');
document.links; // or use the built-in property!
// get all elements with the class foo
var foos = document.getElementsByClassName('foo');
// get elements based on a CSS selector
var els = document.querySelectorAll('code pre');
// get elements based on CSS selector
var el = document.querySelector('code pre'); // only returns the first match
// change CSS properties
document.getElementById('manipulating-demo').style.border = '1px solid #FFF';
document.getElementById('manipulating-demo').style.padding = '20px';
// change text
document.getElementById('manipulating-demo').innerHTML = 'Code has been run, I am changed';
// set 'test' as classname
document.getElementById('manipulating-demo').className = 'test';
// give notice
alert('The element #' + document.getElementById('manipulating-demo').id + ' was changed');
Run example above to change me
// cache the variable
var el = document.getElementById('manipulating-demo2');
// change CSS properties
el.style.border = '1px solid #FFF';
el.style.padding = '20px';
// change text
el.innerHTML = 'Code has been run, I am changed';
// set 'test' as classname
el.className = 'test';
// give notice
alert('The element #' + el.id + ' was changed');
Run example above to change me
var allSpans = document.querySelectorAll('#manipulating-unoptimized span');
for (var i = 0; i < allSpans.length; i++) {
allSpans[i].className = 'test';
allSpans[i].style.border = '1px solid #FFF';
allSpans[i].style.padding = '5px';
allSpans[i].style.margin = '5px';
}
123
var allSpans = document.querySelectorAll('#manipulating-optimized span');
for (var i = 0, len = allSpans.length; i < len; i++) {
var curSpan = allSpans[i];
curSpan.className = 'test';
curSpan.style.border = '1px solid #FFF';
curSpan.style.padding = '5px';
curSpan.style.margin = '5px';
}
456
Element reference
Node#parentNodeNode#childNodes, Node#firstChild, Node#lastChildNode#previousSibling, Node#nextSiblingNode#parentElementNode#children, Node#firstElementChild, Node#lastElementChild
Node#previousElementSibling, Node#nextElementSiblingclick, mouseover, mouseout, ..)keypress, keydown, keyup)submit, reset)loading, a resize of the window, an element gaining focus, etc.#onEventname
var p = document.querySelector('#onevent-demo p');
p.onclick = function() { alert('You clicked me!'); };
p.onmouseover = function() { this.style.backgroundColor = '#333'; };
p.onmouseout = function() { this.style.backgroundColor = ''; };
I am the demo
var p = document.querySelector('#oneventtwice-demo p');
p.onclick = function() { alert('You clicked me (1)!'); };
p.onclick = function() { alert('You clicked me (2)!'); };
p.onmouseover = function() { this.style.backgroundColor = '#333'; };
p.onmouseout = function() { this.style.backgroundColor = ''; };
I am the 2nd demo
#addEventListener
var p = document.querySelector('#addeventlistener-demo p');
p.addEventListener('click', function() {
alert('You clicked me!');
});
p.addEventListener('mouseover', function() {
this.style.backgroundColor = '#333';
});
p.addEventListener('mouseout', function() {
this.style.backgroundColor = '';
});
I am the demo
#addEventListener multiple times for the same event
var p = document.querySelector('#addeventlistenertwice-demo p');
p.addEventListener('click', function() {
alert('You clicked me (1)!');
});
p.addEventListener('click', function() {
alert('You clicked me (2)!');
});
p.addEventListener('mouseover', function() {
this.style.backgroundColor = '#333';
});
p.addEventListener('mouseout', function() {
this.style.backgroundColor = '';
});
I am the demo
#removeEventListener, but only if you've attached a named function
var p = document.querySelector('#removeeventlistener-demo p');
var clickHandler = function() {
alert('You clicked me!');
};
p.addEventListener('click', clickHandler);
p.removeEventListener('click', clickHandler);
p.addEventListener('mouseover', function() {
this.style.backgroundColor = '#333';
});
p.addEventListener('mouseout', function() {
this.style.backgroundColor = '';
});
I am the demo
var divs = document.querySelectorAll('#bubbling-demo div');
for (var i = 0, len = divs.length; i < len; i++) {
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'yellow';
alert(this.className);
this.style.backgroundColor = '';
});
}
Event#stopPropagation
var divs = document.querySelectorAll('#stoppropagation-demo div');
for (var i = 0, len = divs.length; i < len; i++) {
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'yellow';
alert(this.className);
this.style.backgroundColor = '';
event.stopPropagation(); // stop bubbling!
});
}
Event#preventDefault
var link = document.querySelector('#stopdefault-demo a');
link.addEventListener('click', function(event) {
alert('Link is linked to ' + this.href + ' but won\'t be followed');
event.preventDefault(); // prevent the default action from happening
});
return false;
var divs = document.querySelectorAll('#bubblingtarget-demo div');
for (var i = 0, len = divs.length; i < len; i++) {
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'yellow';
alert(this.className + ' (click was on ' + event.target.className + ')');
this.style.backgroundColor = '';
});
}
event.target it's possible to bind the handler on the <table> itself.
var table = document.querySelector('#bubbling-advantage-demo table');
table.addEventListener('click', function(event) {
alert('Table click event (click was on ' + event.target.innerHTML + ')');
});
| 1 | 2 | 3 |
| 4 | 5 | 6 |
var divs = document.querySelectorAll('#capturing-demo div');
for (var i = 0, len = divs.length; i < len; i++) {
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'cyan';
alert(this.className);
this.style.backgroundColor = '';
}, true); // phase parameter!
}
var divs = document.querySelectorAll('#capturing-and-bubbling-demo div');
for (var i = 0, len = divs.length; i < len; i++) {
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'cyan';
alert(this.className);
this.style.backgroundColor = '';
}, true); // capturing phase
divs[i].addEventListener('click', function(event) {
this.style.backgroundColor = 'yellow';
alert(this.className);
this.style.backgroundColor = '';
}, false); // bubbling phase
}
var link,
target = Reveal.getCurrentSlide().querySelector('.result');
target.innerHTML = ''; // clear the target
for (var i = 0; i < 3; i++) { // add three links
link = document.createElement('a');
link.style.marginRight = '10px';
link.innerHTML = 'Link ' + i;
link.onclick = function() {
alert('I am link ' + i);
};
target.appendChild(link);
};
onclick, a function is created

Here we go again!
var link,
target = Reveal.getCurrentSlide().querySelector('.result');
target.innerHTML = ''; // clear the target
for (var i = 3; i < 6; i++) { // add three links
link = document.createElement('a');
link.style.marginRight = '10px';
link.innerHTML = 'Link ' + i;
var j = i; // introduction of a local variable
link.onclick = function() { // function created, ergo closure created!
alert('I am link ' + j);
};
target.appendChild(link);
};
var toSay = 'Run Forrest, Run';
(function(sentence) {
console.log(sentence);
})(toSay);
var link,
target = Reveal.getCurrentSlide().querySelector('.result');
target.innerHTML = ''; // clear the target
for (var i = 6; i < 9; i++) { // add three links
link = document.createElement('a');
link.style.marginRight = '10px';
link.innerHTML = 'Link ' + i;
link.onclick = function(j) { // This one just became an IIFE
return function() { // and returns a function
alert('I am link ' + j);
};
}(i);
target.appendChild(link);
}
<!doctype html>
<html>
<head>
...
<script>
alert('hello');
</script>
...
</head>
<body>
...
</body>
</html>
alert before the page is being rendered!<!doctype html>
<html>
<head>
...
<script src="path/to/my.js"></script>
...
</head>
<body>
...
</body>
</html>
</body>, to not block parallel downloads
<!doctype html>
<html>
<head>
...
</head>
<body>
...
<script src="path/to/my.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
...
</head>
<body>
...
<script src="path/to/my.js"></script>
</body>
</html>
window.onload = function() {
// ... your code here
};
addEventListener
document.addEventListener('load', function(event) {
// ... your code here
}, false);
load is fired when everything (including images) is loaded. Most of the time you'll want to invoke your scripts when the DOM has loaded.
document.addEventListener('DOMContentLoaded', function(event) {
// ... your code here
}, false);
animate, but then include a library that defines the same function with the same name
ikdoeict_) but that isn't quite professional
var IKDOEICT = {
foo : {
bar : function(x) { return x; },
baz : function(x) { return x; }
},
foobar : {
foo : function(x) { return x; },
bar : function(x) { return x; },
baz : function(x) { return x; }
}
};
alert(IKDOEICT.foobar.foo('test'));
// file 1
var IKDOEICT = IKDOEICT || {}; // use existing IKDOEICT, or create a new Object
IKDOEICT.foo = {
bar : function(x) { return x; },
baz : function(x) { return x; }
};
// file 2
var IKDOEICT = IKDOEICT || {}; // use existing IKDOEICT, or create a new Object
IKDOEICT.foobar = {
foo : function(x) { return x; },
bar : function(x) { return x; },
baz : function(x) { return x; }
};
// test
alert(IKDOEICT.foo.baz('test'));
var IKDOEICT = IKDOEICT || {};
(function(o){
o.foo = {
bar : function(x) { return x; },
baz : function(x) { return x; }
}
o.foobar = {
foo : function(x) { return x; },
bar : function(x) { return x; },
baz : function(x) { return x; }
}
})(IKDOEICT);
// test
alert(IKDOEICT.foo.baz('test'));
var IKDOEICT = (function(){
var privateFunction = function() { return; }
return {
foo : {
bar : function(x) { return x; },
baz : function(x) { return x; }
},
foobar : {
foo : function(x) { return x; },
bar : function(x) { return x; },
baz : function(x) { return x; }
}
};
})();
// test
alert(IKDOEICT.foo.baz('test'));
</body>DOMContentLoaded
for...in these will appear inside your loop
Object#hasOwnProperty inside your loop