JavaScript - From Birth To Closure

133
JavaScript From birth to closure

description

This presentation will give you a brief background to JavaScript, what it is and where it comes from. Then it will walk you through general pitfalls, best practices and more advanced topics such as object-orientation, scope and closures.

Transcript of JavaScript - From Birth To Closure

JavaScriptFrom birth to closure

Yeah, nothing

Brendan Eich

Brendan Eich

What is JavaScript?

• Developed by Brendan Eich 1995

• Initially called Mocha, then LiveScript

• First day of light in a beta of Netscape 2 in December 1995

• IE followed suit with JScript in 1996

“You’re number one!”

Has NOTHING to do with Java!

• JavaScript is one of the world’s most popular programming languages

• One interpreter on every machine

• ECMAScript standardizing - Fifth edition

• Web browsers becoming much faster

Douglas Crockford

Douglas Crockford

JavaScript basics

Variable declaration:

var benAffleck = ”Actor”;

Function declaration:

function benQuote () {! return "Rumors about me?

Calista Flockhart, Pam Anderson, and Matt Damon. That's who I'm dating.";

}

Conditionals

• If

• Switch

• Shorthand assignment

• Ternary operators

function makeMovie (withLivTyler) {! var nice = withLivTyler || false;}

(datedJLo)? "Lucky guy!" : "No?";

Comparison operators

• = Assignment

• == Equality

• === Identity

// Assignmentvar bestFriend = "Matt Damon";

// Equalityif (5 == "5") {!// true}

// Identityif (5 === "5") {!// false}

// Short-circuit logicif (true || false)

if (false && true)

// Makes this code safeif (obj && obj.property)

// Short-circuit logicif (true || false)

if (false && true)

// Makes this code safeif (obj && obj.property)

Type coercion

// true5 == "5"

// 123"1" + 2 + 3;

// 6, manual type conversionparseInt("1", 10) + 2 + 3;

null == undefined == 0 == false == ""

• Not really, but sort of

• Rather “truthy” or “falsy”

var a = null;var b; // undefinedvar c = 0;var d = false;var e = "";

if (a) // falseif (b) // falseif (c) // falseif (d) // falseif (e) // false

JavaScript data types

• string

• number

• boolean

• null

• undefined

• Object

Types of Object include:

• function

• Array

• Date

• RegExp

Checking type

typeof return values:

• string

• number

• boolean

• function

• object

• undefined

typeof fanClub // "undefined"

var title = "Armageddon";

typeof title // Equals "string"

var age = 37;

typeof age // Equals "number"

function anotherQuote () {! return "If I ever woke up

with a dead hooker in my hotel room, Matt would be the first person I'd call.";

}typeof anotherQuote; //"function"

var obj = {};

typeof obj = // "object"

var arr = ["B", "E", "N"];

typeof arr // "object"

var obj = {};

typeof obj = // "object"

var arr = ["B", "E", "N"];

typeof arr // "object" ?!

Using instanceof

obj instanceof Array // false

arr instanceof Array // true

Functions

Procedural

function notAHit () {! return "Gigli";}

Functions as variables

var wroteScript = function () {! return "Good Will Hunting";};wroteScript();

Anonymous

document.onmousemove = function (evt) {alert(evt.pageX);

};

Self-invoking

(function () {! var dogma = "Shot in 1999";})();

Self-invoking

(function () {! var dogma = "Shot in 1999";})();

Function arguments

• Any argument can be omitted

• Any argument can be added

• No overloading

• The arguments collection

function concat (a, b, c) {! return a + b + c;}

concat(1, 2, 3); // 6concat(1, 2); // NaN

• The arguments collection

• Property: arguments.length

• NOT an array

function concat () {! var sum = 0,

l = arguments.length;! for (var i=0; i<l; i++) {! ! sum += arguments[i];! }! return sum;}concat(1, 2, 3); // 6concat(1, 2); // 3concat(1, 2, 7, 11, 5); // 26

Objects

function Ben () {! this.name = "Ben Affleck";! this.gotAnOscar = true;};

var ben = new Ben();alert(ben.gotAnOscar); // true

Object constructor

var ben = {! name : "Ben Affleck",! gotAnOscar : true};

alert(ben.name); // "Ben Affleck"

Object literal

Different syntax, same thing:

ben["arms"] = 2;

ben.arms = 2;

Different syntax, same thing:

ben["arms"] = 2;

ben.arms = 2;

For any object:

var ben = {};

ben[1972] = "Year of birth";

ben["born"] = 1972;

ben[true] = false;

var regEx = new RegExp;

regEx[3] = "I can do this?";

var goodMovie = {! title : "Good Will Hunting",! year : 1997};

for (var item in goodMovie) {! alert(item + ": " + goodMovie[item]);}

var goodMovie = {! title : "Good Will Hunting",! year : 1997};

// Check returns trueif ("year" in goodMovie) {! alert(goodMovie.year);}

Inheritance

• Prototype-based inheritance

• Not class-based

• The prototype chain checks itself first

• It then goes to the parent, parent’s parent etc...

function Being () {! this.living = true;}

Being.prototype.greet = function () {! return "Hello!";};

function Ben () {

! this.talks = true;

}

Ben.prototype = new Being;

Ben.prototype.saySomething = function () {

! return "I feel like fame is wasted on me.";

};

// Create an instance

var ben = new Ben();

// Returns "I feel like fame is wasted on me."

ben.saySomething();

// Returns "Hello!", inherited

// from the Being object

ben.greet();

Checking for the greet() method in this order:

• ben instance

• Ben prototype

• Being prototype

• Object prototype

• It’s native, i.e. no dependencies

• Freedom of style and version

• Easy readability

• Code handover

Why prototype syntax

“I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function...

...I now see my early attempts to support the classical model in JavaScript as a mistake.”

- Douglas Crockford

Why prototype syntax

Scope

• Scope refers to where variables and functions are accessible

• In what context something is being executed

• Basically, global or local

• Variables have function scope

• Functions have the same scope as variables

// Globalvar likesToPlay = "Poker";

function getGame () {! // Local! var likesToPlay = "Hold ‘em";

! // Global! playOnline = true;

! return likesToPlay;! // Returns "Hold ‘em"}

function playPoker (money) {! if (money) {! ! var willPlay = true;! }

! // Perfectly valid! return willPlay;}

function global () {! return "Access anywhere";}

function outer () {! function inner () {! ! return "Inner";! }! return inner();}outer(); // Accessibleinner(); // Not accessible

“Global scope is like a public toilet.

You can’t avoid going in there. But try to limit your contact with surfaces when you do.”

- Dmitry Baranovskiy, Raphaël JS library

Polluting the global namespace

Function scope

• Run a function in a certain context

• The call and apply methods

• Defined for all functions

function docReady () {! alert(this);! // this is the window object}window.onload = docReady;

function setName (name) {! this.name = name;! // document.name === "Bennifer"}

document.onclick = function () {! setName.call(document, "Bennifer");};

function setName (name) {! this.name = name;! // document.name === "Bennifer"}

document.onclick = function () {! setName.call(document, "Bennifer");};

function setNames () {! this.firstName = arguments[0];! this.lastName = arguments[1]; // document.firstName === “Ben” // document.lastName === “Affleck”}

function callSetNames () {! setNames.apply(document, arguments);};callSetNames("Ben", "Affleck");

function setNames () {! this.firstName = arguments[0];! this.lastName = arguments[1]; // document.firstName === “Ben” // document.lastName === “Affleck”}

function callSetNames () {! setNames.apply(document, arguments);};callSetNames("Ben", "Affleck");

Closures

• Closures are expressions, usually functions, which can work with variables set within a certain context

• Inner functions referring to local variables of its outer function create closures

function add (x) {! return function (y) {! ! return x + y;! };}var add5 = add(5);var no7 = add5(2); // Equals 7

“Right... What?!”

function add (x) {! return function (y) {! ! return x + y;! };}var add5 = add(5);

// How JavaScript sees itvar add5 = function (y) {! return 5 + y;}

function add (x) {! return function (y) {! ! return x + y;! };}var add5 = add(5);

// How JavaScript sees itvar add5 = function (y) {! return 5 + y;}

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function () {

! ! ! alert(i);

! ! };

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function () {

! ! ! alert(i);

! ! };

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

! ! link.onclick = function () {

! ! ! alert(i);

! ! };

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

function addLinks () {

! for (var i=0, link; i<5; i++) {

! ! link = document.createElement("a");

! ! link.innerHTML = "Link " + i;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

! ! document.body.appendChild(link);

! }

}

window.onload = addLinks;

! ! link.onclick = function (num) {

! ! ! return function () {

! ! ! ! alert(num);

! ! ! };

! ! }(i);

Yahoo JavaScript Module Pattern

• Origins from Douglas Crockford

• Singleton pattern

• Offers private and public members

var goneBabyGone = function () {

! // Private members

! var movieTitle = "Gone Baby Gone",

isDirectedByBen = true;

!

! // Public members

! return {

! ! title : function () {

! ! ! return movieTitle;

! ! },

! !

! ! directedByBen : function () {

! ! ! return isDirectedByBen;

! ! }

! };

}();

var goneBabyGone = function () {

! // Private members

! var movieTitle = "Gone Baby Gone",

isDirectedByBen = true;

!

! // Public members

! return {

! ! title : function () {

! ! ! return movieTitle;

! ! },

! !

! ! directedByBen : function () {

! ! ! return isDirectedByBen;

! ! }

! };

}();

var goneBabyGone = function () {

! // Private members

! var movieTitle = "Gone Baby Gone",

isDirectedByBen = true;

!

! // Public members

! return {

! ! title : function () {

! ! ! return movieTitle;

! ! },

! !

! ! directedByBen : function () {

! ! ! return isDirectedByBen;

! ! }

! };

}();

var goneBabyGone = function () {

! // Private members

! var movieTitle = "Gone Baby Gone",

isDirectedByBen = true,

! ! title = function () {

! ! ! return movieTitle;

! ! },

! !

! ! directedByBen = function () {

! ! ! return isDirectedByBen;

! ! };

!

! // Public members

! return {

title : title,

directedByBen : directedByBen

! };

}();

Namespacing

• Avoiding global variables

• Code structure

• Extending, but not necessarily inheriting

// Create a Ben object

var Ben = {};

// Set functionality

Ben.Director = function () {

! var noOfMovies = 4;

! return {

! ! movies : function () {

! ! ! return noOfMovies;

! ! }

! };

}();

// Assertion

if (typeof Ben === "undefined") {

! Ben = {};

}

Ben.Actor = function () {

! var noOfMovies = 51;

! return {

! ! actAndDirectorCount : function () {

! ! ! return noOfMovies + " as actor & "

+ Ben.Director.movies.call(this)

+ " as Director";

! ! }

! };

}();

Sugar & spiceIt’s awfully nice!

• Sugaring

• Currying

// A little sugar

String.prototype.trim = function () {

! return this.replace(/^\s*|\s*$/g, "");

};

var monkey = " Monkey ";

monkey.trim(); //"Monkey"

// Currying

function add () {

! var sum = 0;

! for (var i=0, il=arguments.length; i<il; i++) {

! ! sum += arguments[i];

! };

! return sum;

}

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

// Currying (continued) - Currying method by Crockford!!

Function.prototype.curry = function () {

! var slice = Array.prototype.slice,

! ! args = slice.apply(arguments),

! ! that = this;

! return function () {

! ! ! return that.apply(

! ! ! ! null, args.concat(slice.apply(arguments))

! ! ! );

! };

}

var add8 = add.curry(5, 3);

alert(add8(1, 3, 7)); // 19

Syntax recommendations

• No real standard, only best practices

• Recommended tool: JSLint

Embrace JavaScript

• Embrace JavaScript

• Don’t try to make it into Java, C or any other language

• Learn to love it and its dynamic, loose and prototypical nature

This is how we roll

Robert Nymanrobertnyman.com/speaking/[email protected]

Twitter: @robertnyman

Pictures:Brendan - http://www.flickr.com/photos/mollyeh11/279367481/Yoda - http://buzzybeegirl.files.wordpress.com/2008/12/yoda-400x3001.jpgTwitter - http://twitter.com/manssandstrom/status/1528315581Gmail - http://www.flickr.com/photos/webber/71748774/Slow - http://www.feministing.com/archives/012345.htmlCrockford - http://www.flickr.com/photos/charliebrewer/2897862701/Obi-Wan - http://enterthecircle.files.wordpress.com/2009/01/obi-wan-kenobi-01-large.jpgBen Affleck - http://www.flickr.com/photos/sasy/3993866442/Squat toilet - http://www.flickr.com/photos/35034350906@N01/4080372999Cuddling bears - http://www.nogg.se/blogg.asp?intShowMenu=a2&idHomepage=6951&idBloggCategory=6162Winnie The Pooh and friends - http://mammacarola.blogg.se/2009/april/IE Voodoo Doll - http://nexus404.com/Blog/2007/10/26/make-your-own-internet-explorer-voodoo-doll-a-step-by-step-guide/Ben Affleck confused - http://cdn.buzznet.com/assets/imgx/4/9/0/5/8/orig-49058.jpg