Sie sind auf Seite 1von 246

Advanced

JavaScript
Jussi Pohjolainen

Agenda

Short Recap of JS
About EcmaScript 5
JavaScript Best Prac>ces and Pa?erns
JavaScript Object Oriented Programming
HTML5 and JavaScript
JS libraries
JQuery, YUI Library -> AngularJS

Asynchronous Module Deni>on (AMD)


Designing JS Libraries
Tes>ng & Op>mizing

Recommended Reading
Recommended reading
JavaScript: The Good Parts by Douglas Crockford
JavaScript: The Denite Guide by David Flanagan
JavaScript Pa?erns: Stoyan Stefanov

And Google..
Lot of good presenta>ons
http://yuilibrary.com/theater/

Rise of the Responsive Single Page App

Image: h?p://johnpolacek.github.io/scrolldeck.js/decks/responsive/

Single-page Applica>ons (SPA)


Web app that ts on a single web page
Fluid UX, like desktop app
Examples like Gmail, Google maps

Html page contains mini-views (HTML


Fragments) that can be loaded in the
background
No reloading of the page, be5er UX
Requires handling of browser history,
naviga<on and bookmarks

JavaScript
SPAs are implemented using JavaScript and
HTML
ECMAScript is a scrip>ng language,
standardized by Ecma Interna>onal
In Browsers, ECMAScript is commonly called
JavaScript
JavaScript = Na<ve (EcmaScript) + Host objects
(browser)

Not just Web!

Mobile Applica>ons
Windows 8/10 apps
Desktop widgets
Server side JS

<!DOCTYPE html>
<html>
<head>
<title>
Title
</title>
<meta charset="UTF-8" />
</head>
<body>
<script>
document.write("hello world!");
</script>
<script src="somefile.js"></script>
</body>
</html>

PROGRAMMING WITH JS

Basic Types
JavaScript is loosely typed language!
Seven data types
Boolean
null
Undefined
Number
64 bit oa>ng point, also available Number.MAX_VALUE,
Number.MIN_VALUE

String
Object

About Numbers
Number(value), converts en>re string
var i = Number("12");

parseInt(value[, radix]), converts start of the


string
var i = parseInt("12px", 10);
Radix?

10 => integer number, 8 => octal number, 16 => hexadecimal


While this parameter is op>onal, always specify it to eliminate
reader confusion and to guarantee predictable behavior. Dierent
implementa<ons produce dierent results when a radix is not
specied.

NaN (Not a Number)

Result of erroneous opera>ons

var integer1 = Number("12");


var integer2 = parseInt("12", 10);
print(integer1 + integer2);
// 24
var a = parseInt("12foobar", 10);
print(a);
// 12
var b = parseInt("
print(b);
// 12

12

", 10);

var c = parseInt("foobar12", 10);


print(c);
// Don't do this
if(c == NaN)
{
print("A) It's Nan!");
}
if(isNaN(c))
{
print("B) It's NaN!");
}

Math Object
All proper>es and methods are "sta>c", just
like in Java
abs
acos
atan

sin
sqrt

var value = Math.sqrt(4);

Strings
Sequences of 0 n of 16-bit chars
Example
var s1 = "Hello";
var s2 = "Hello";
if(s1 === s2)
{
print("the same!");
}
print(s1.length);
print("hello" + 12);
print(12 + "hello");
print("hello".toUpperCase());

True or false?
var myArray1 = [false, null, undefined, "", 0,
NaN];
// EcmaScript 5 feature!
// Iterate the array
myArray1.forEach(function(entry)
{
if(entry)
{
print(entry);
// Here?
}
});

True or false?
var myArray1 = ["false", "0", "undefined", "NaN"];
// EcmaScript 5 feature!
// Iterate the array
myArray1.forEach(function(entry)
{
if(entry)
{
print(entry);
}
});

True or false?
var value = 0;
if(value = 0)
{
print("A");
}
if(value == 0)
{
print("B");
}
if("0" == 0)
{
print("C");
}
if("0" === 0)
{
print("D");
}

Statements
Same than in other languages
If
Switch/case
While
Do/while
For
Break
Con>nue
Return
Try/throw/catch

Rhino (JavaScript Engine)


Open Source JS Engine developed in Java
Mozilla Founda>on

No built in support for web browser objects


Has Rhino shell for running JS in command line
Is bundled in Java SE 6
Supports EcmaScript 5

EXERCISE 1

ABOUT ECMASCRIPT 5

EcmaScript
Ecma Standard is based on JavaScript (Netscape)
and JScript (Microsom)
Development of the standard started in 1996
First edi>on 1997
Support
http://kangax.github.com/es5-compat-table/

Newest version: EcmaScript 5.1


http://www.ecma-international.org/
publications/files/ECMA-ST/Ecma-262.pdf

Recap: object types


Na>ve (Core Javascript)
ECMAScript standard: Array, Date..

Host
The host environment, for example browser:
window, DOM objects

EcmaScript
Goal
Fix bad parts of JS while maintaining compa>ble
with EcmaScript 5

Introduces Strict mode


Removes features from the language! Raises errors
that were okay in non strict mode
Backward compa>ble
Add use strict, in func>on or global scope

EcmaScript supports non-strict mode, but its


depricated!

Strict mode
Detec>on of bad/dangerous programming
prac>ces
with() statement prevented
Assignment to non-declared variables prevented (i
= 3)
Eval is prohibited
Lot of other issues..

See ES5 specica>on page 235

Enable strict mode


> cat strictmode.js
// This is just a string, backward compatible!
"use strict";
i = 0;
> rhino strictmode.js
js: uncaught JavaScript runtime exception:
ReferenceError: Assignment to undefined "i" in
strict mode

Global and local


// GLOBAL, everything is strict:
"use strict";
//.. strict program
// LOCAL, function is strict
function foo()
{
"use strict";
//.. strict function
}

Other Main Changes


Na>ve JSON object added
For parsing/stringifying JSON

Changes to Array object, nine new methods


indexOf, lastIndexOf, every, some, forEach, map,
lter, reduce, reduceRight

Changes to Object
Can dene ge?ers and se?ers
Objects can be sealed (no new proper>es can be
added) and frozen (values cannot be changed)

JSON and Weather Underground


myObject = JSON.parse(httpObj.responseText);
city = myObject.location.city;
now = myObject.forecast.txt_forecast.forecastday[0].fcttext_metric;
icon = myObject.forecast.txt_forecast.forecastday[0].icon_url;

forEach
var arr = ["apple", "banana", "carrot", "apple"];
print(arr.indexOf("apple"));
// 0
print(arr.indexOf("daikon"));
// -1
print(arr.lastIndexOf("apple")); // 3
arr.forEach(function (entry)
{
print(entry)
}
);

every and some


// Checks all the values, if one of them does not
// match with given condition, return value is false.
var returnValue = arr.every(function (value, index, array)
{
return value.length > 1;
}
);
print(returnValue); // true
// Checks all the values, if one of them matches with
// given condition, return value is true.
var returnValue = arr.some(function (value, index, array)
{
return value === "apple";
}
);
print(returnValue); // true

map and lter


// Adds Hello to the end of the array values
var newArray = arr.map(function (value, index, array) {
return value + " Hello";
});
newArray.forEach(function (entry)
{
print(entry)
}
);
// Keep only Apples.
var newArray2 = arr.filter(function (value, index, array) {
return value === "apple";
});
newArray2.forEach(function (entry)
{
print(entry)
}
);

reduce
var value = [10, 20, 30,
print("previousValue =
print("currentValue =
return previousValue +
}, 0);

40, 50].reduce(function (previousValue, currentValue, index, array) {


" + previousValue);
" + currentValue);
currentValue;

print("result = " + value);


/*
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
result = 150
*/

=
=
=
=
=
=
=
=
=
=

0
10
10
20
30
30
60
40
100
50

reduceRight
var value = [10, 20, 30,
print("previousValue =
print("currentValue =
return previousValue +
}, 0);

40, 50].reduceRight(function (previousValue, currentValue, index, array) {


" + previousValue);
" + currentValue);
currentValue;

print("result = " + value);


/*
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
previousValue
currentValue
result = 150
*/

=
=
=
=
=
=
=
=
=
=

0
50
50
40
90
30
120
20
140
10

Prevent Extensions
"use strict";
var obj = {};
obj.name = "John";
print(obj.name);
// "John"
print(Object.isExtensible(obj));

// true

Object.preventExtensions(obj);
// Should be exception in strict mode
obj.url = "http://www.something.com";
print(Object.isExtensible(obj));

Proper>es and Descriptors


Its possible to dene proper>es for object
Property descriptor
Value
Get and Set methods
Writable
Enumerable
Congurable

Example
var obj = {};
obj.name = "something";
Object.defineProperty( obj, "name", {
value: "something", // Notice: you cannot have value and get + set
get: someFunction,
set: someOtherFunction,
writable: false,
// property cannot be changed
enumerable: true, // will be iterated in for in
configurable: true // can be deleted
});
print( obj.name )

Sealing and Frozing


Sealing prevents other code from dele>ng or
adding descriptors
Object.seal(obj)
Object.isSealed(obj)

Frozing is almost iden>cal to sealing, but


addi>on of making the proper>es uneditable
Object.freeze(obj)
Object.isFrozen(obj)

EcmaScript 5 - Overview

Strict Mode
JSON parsing now standard
New Array methods
New Object methods

EXERCISE 2

JS BEST PRACTISES AND PATTERNS

Tools
IDEs
Visual Studio, Aptana, Webstorm, IxEdit
Or just text editor

JS Engines: V8, Rhino ..


Quality: JSLint
Lot of frameworks available!

JS and OO
JavaScript supports object-oriented language!
Only ve primi>ve types: number, string,
boolean, null, undened
Object wrappers for number, string and boolean
available

Object is just a collec>on of named proper>es, a


list of key-value pairs
Some of the proper>es can be func>ons!

No classes! Lets look at OO later in more


carefully.

JS and Command Line


Its possible to run your js apps in command
line.
Several JS engines
SpiderMonkey (c++) or Rhino (java) (Firefox)
SquirrelFish (Apples Webkit)
V8 (Google Chrome)

Its possible to install these as command line


apps, although the process can be li?le
dicult

Rhino (JavaScript Engine)


Open Source JS Engine developed in Java
Mozilla Founda>on

No built in support for web browser objects


Has Rhino shell for running JS in command line
Is bundled in Java SE 6
In Java 8 a new JS engine called Nashorn

V8
Open source JS engine developed by Google
Compiles JS to na>ve code
Wri?en in C++, runs on Windows, OS X and
Linux
Can be used in browser and standalone
engine
You need to build the V8
h?p://code.google.com/p/v8/
h?ps://developers.google.com/v8/build

V8 running on Mac OS X

Any problems in the code?


function sum (a, b)
{
s = a + b;
return s;
}
x = sum(5,5);
// Rhino's way to print to console
print (x);

JSLint
JSLint is JS code quality tool made by Douglas
Crockford
h?p://jslint.com

Inspects and warns about poten>al problems


Will hurt your feelings
Excepts that your code is in strict mode
Can be used via website or command line
(installa>on required)
Command line tool (Java wrapper for JSLint)

h?p://code.google.com/p/jslint4java/

JSLint in Command Line


JSLint4java Java wrapper for the JSLint
h?p://code.google.com/p/jslint4java/

To use it:
java -jar jslint4java-2.0.3.jar applica>on.js

Amer some modica>ons


function sum(a, b) {
"use strict";
var s = a + b;
return s;
}
var x = sum(5, 5);
// Rhino's way to print to console
print(x);

Prin>ng to Console
Debugging in Browsers: use console object
Firefox
Firebug extension

Safari
Enable developer mode

How?
console.log(Hello World!);

Global Variables
Every JS environment has a global object
Every global variable becomes a property of
the global object
In browser environment: window is the global
object itself

Declaring Global variable


// global object, window, will get a new property!
variable = "hi there!";
console.log(variable);
// And different ways to access the variable
console.log(window.variable);
console.log(window.variable);
console.log(window["variable"]);
console.log(this.variable);
console.log(window);

Window proper>es

Problems
Global variables shared among all the code
What if you use some third party JavaScript
Library like JQuery or Modernizr? Name
collision!
Avoid Globals!

Problem 1
function something() {
// window object now has variable property!
variable = "hi there!";
}
something();
// prints "hi there!"
console.log(variable);

Problem 2
function something() {
// window object now has z property!
var x = z = "hello";
}
something();
// prints "hello"
console.log(z);

Dierence when using var


var x = 20;
y = 21;
console.log(window.x);
console.log(window.y);

// 20
// 21

delete x; // does not delete anything


delete y; // removes the y from window
console.log(window.x);
console.log(window.y);

// 20
// undefined

Using var
Use always var!
In strict mode, assignments to undeclared
variables will throw an error!

Func>ons and Variable Declaring


var x = 10;
function test() {
console.log(x);
if(true) {
var x = 5;
}
}
test();

// outputs what?

What really happens


var x = 10;
function test() {
var x;
console.log(x);
if(true) {
x = 5;
}
}
test();

// outputs undefined

Variable Hois>ng
When you declare a variable inside a func>on,
it acts like it was declared at the top of the
func>on!
Declare always your variables at the top!

Single Var Pa?ern


function test() {
var a = 1,
b = 2,
;
// rest of the function
}
test();

FD, FE, NFE


It gets harder when a variable is
Func>on declara>on (FD)
Func>on expression (FE)

Rules
Func<on declara<on is not hoisted
Func<on expression is hoisted

Func>on Declara>on: this works!


function testC()
{
print(foo());
function foo()
{
return 5;
}
}
<=>
function testD()
{
function foo()
{
return 5;
}
print(foo());
}

Func>on Expression: this does not work!


function testA()
{
print(foo());
var foo = function()
{
return 5;
}
}
<=>
function testB()
{
var foo;
print(foo());
foo = function()
{
return 5;
}
}

Named Func>on Expression


// Named function expression for recursion or debugging
var somethingFoo = function somethingBar()
{
print("do something");
// Recursion, does not end well here.
somethingBar();
}
somethingFoo();
// this does not work
somethingBar();

Func>ons in if-statements
In strict mode code, func:ons can only be
declared at top level or immediately within
another func:on.
So what happens in non-strict mode?

Func>ons in if-statements
function init()
{
if(true)
{
function foo() { return 1; }
}
else
{
function foo() { return 2; }
}
return foo();
}
print(init());

// 1 or 2?

Use this!
function init2()
{
var foo;
if(true)
{
foo = function() { return 1; }
}
else
{
foo = function() { return 2; }
}
return foo();
}
print(init2());

For loops
for(var i = 0; i < somearray.length; i++) {
doSomething();
}
<=>
var max = somearray.length;_for(var i = 0; i < max; i++) {
doSomething()
}

Comparison
false == 0 => true
== 0
=> true
Use
false === 0 => false
=== 0
=> false

eval()
eval() func>on takes JS (string) and executes
it.
Security issues: dont use it!
To parse JSON objects, use JSON.parse();

with
// Instead of doing this, you could
myobj.prop.subprop.subsubprop.a = true;
myobj.prop.subprop.subsubprop.b = false;
// .. Use shortcut using with.. But DONT!
with(myobj.prop.subprop.subsubprop)
{
a = true;
b = true;
}
// Its confusing, just use
var s = myobj.prop.subprop.subsubprop;
s.a = true;
s.b = true;

Constructors
function Person(name) {
this.name = name;
}
// Should be used
var jaska = new Person("Jaska");
// Don't! Now this is bound to global object
var jeppe = Person("Jeppe");

Be?er version
function Person(name) {
// If this refers not to Person (for example global object)
if(!(this instanceof Person))
{
// Let's then use the new word
return new Person(name);
}
else
{
this.name = name;
}
}
// Now both work
var vilma = new Person("Vilma");
var jaska = Person(Jaska");

Code Style
Indenta>on: 4 spaces (default for JSLint)
Use always curly braces
Naming conven>ons:
Use capital le?er in constructor func>ons:
var jack = new Person();

Documen>ng your code


Its possible to generate documenta>on from
your comments (like Javadoc in Java)
Free tools like
JSDoc3
h?p://usejsdoc.org/about-gezng-started.html

Minimizing your code


The Closure Compiler is a tool for making
JavaScript download and run faster
Google Closure Compiler
h?ps://developers.google.com/closure/compiler/

Can be user by command line or web


h?p://closure-compiler.appspot.com/home

EXERCISE 3

HTML5 AND JS

HTML5
Fimh version of HTML standard by W3C
S>ll under development but lot of browsers support
the proposal of the standard
Simple markup that can be wri?en either in HTML or
XHTML syntax
Poten>al candidate for cross plahorm mobile apps
Mostly about seman<cs, most of the cool parts are
implemented using JavaScript
JS APIs are not part of HTML5, developed separately

New Syntax

<video>
<audio>
<canvas>
<section>, <article>, <header>, <nav>

New JS APIs
Web Storage
The ability to store data locally in browser
Session storage and local storage

Geoloca<on API
Fetching GPS loca>on

File API
Reading local les
See: h?p://www.html5rocks.com/en/tutorials/le/dndles/ or
h?ps://developer.mozilla.org/en-US/docs/Using_les_from_web_applica>ons

Web Workers
Asynchronous methods

Web Sockets
Connec>ng in real>me between client and server. Mul>player games, chat, real>me
upda>ng. Needs server support
h?p://www.developerfusion.com/ar>cle/143158/an-introduc>on-to-websockets/

Canvas

Geoloca>on API
Geoloca>on API Specica>on
h?p://dev.w3.org/geo/api/spec-source.html

To detect the loca>on of the client


In mobile: GPS, in desktop IP-address or Wi-Fi
loca>on

function setText(val, e) {
document.getElementById(e).value = val;
}
function insertText(val, e) {
document.getElementById(e).value += val;
}
var nav = null;
function requestPosition() {
if (nav == null) {
nav = window.navigator;
}
if (nav != null) {
var geoloc = nav.geolocation;
if (geoloc != null) {
geoloc.getCurrentPosition(successCallback);
}
else {
alert("geolocation not supported");
}
}
else {
alert("Navigator not found");
}
}
function successCallback(position)
{
alert("" + position.coords.latitude + ", " + position.coords.longitude);
}

Showing Map on Google API


h?p://maps.googleapis.com/maps/api/
sta>cmap?
center=<la>tude>,<longitude>&zoom=10&siz
e=200x200&maptype=roadmap
See:
h?ps://developers.google.com/maps/
documenta>on/sta>cmaps/

Wunderground + Geoloca>on +
Google sta>c map
Wunderground provides JSON API for weather
informa>on
Get loca>on of the browser and AJAX request
to wunderground
Amer receiving the result, parse it and show
results in html.
Problem: AJAX does not work cross site.. You
can implement middleware (PHP)

Mobile App (iPhone)

Web app!

Mobile App (iPhone)

Canvas
The canvas element a resolu:on-dependent
bitmap canvas, which can be used for
dynamically rendering of images such as game
graphics, graphs, or other images
Image is drawn in JavaScript using typical vector
graphics drawing primi>ves
drawImage(), lineTo(), arcTo(), bezierCurveTo(),
llRect(), scale(), rotate(), translate(),
createLinearGradient(), shadowBlur(),

Simple Drawing using Canvas and JS


<canvas id="mycanvas" width="200" height="200">
</canvas>
<script>
var canvas= document.getElementById('mycanvas');
var context = canvas.getContext('2d');
context.fillRect(60,30,80,120);
</script>

Possibili>es

Simple shapes (Rectangles)


Complex shapes (Paths)
Lines
Shadows
Text
Images
Pixel manipula>on
Colors and styles
Composi>ng
Transforma>ons
Canvas state

Implemen>ng a Game

main
function main() {
createCanvas();
// Original position
reset();
// Millisecs elapsed since 1970.
then = Date.now();
loadImages();
setEventListeners();
//The setInterval() method calls a function or evaluates an expression at
//specified intervals (in milliseconds).
setInterval(gameLoop, 1);
}
window.onload=function(){
main();
}

Game Objects and Global Variables


var
var
var
var
var
var

keysDown = {};
bgImage = null;
canvas = null;
ctx
= null;
then;
monstersCaught = 0;

// Game objects
var hero = {
speed: 256,
x: 0,
y: 0,
myImage: null
};
var monster = {
x: 0,
y: 0,
myImage: null
};

Game Loop
function gameLoop () {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
render();
then = now;
};

Create Canvas
function createCanvas() {
// Create canvas element
canvas = document.createElement("canvas");
// Get the canvas object that you can use to draw
ctx = canvas.getContext("2d");
// Set size for the canvas object
canvas.width = 512;
canvas.height = 480;
document.getElementById("here").appendChild(canvas);
}

Star>ng point
function reset() {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
};

Load Image
function loadImage(imageSrc) {
var image = new Image();
image.src = imageSrc;
return image;
}
function loadImages() {
hero.myImage
= loadImage("lib/hero.png");
monster.myImage = loadImage("lib/monster.png");
bgImage
= loadImage("lib/background.jpg");
}

Key Listeners
function setEventListeners() {
// If keydown, then add the key to the array and set it true
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
// If keyup, remove it from the array
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
}

Update
function update (modifier) {
if (38 in keysDown) { // Player holding
hero.y -= hero.speed * modifier;
}
if (40 in keysDown) { // Player holding
hero.y += hero.speed * modifier;
}
if (37 in keysDown) { // Player holding
hero.x -= hero.speed * modifier;
}
if (39 in keysDown) { // Player holding
hero.x += hero.speed * modifier;
}
// Are they touching?
if (
hero.x <= (monster.x + 32)
&& monster.x <= (hero.x + 32)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)
) {
++monstersCaught;
reset();
}
};

up

down

left

right

Render
function render() {
ctx.drawImage(bgImage, 0, 0);
ctx.drawImage(hero.myImage, hero.x, hero.y);
ctx.drawImage(monster.myImage, monster.x, monster.y);
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "12px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("FB Monsters caught: " + monstersCaught, 20, 20);
};

EXERCISE 4

JS AND OO

About Objects
Everything (except basic types) are objects
Including func>ons and arrays

Object contains proper>es and methods


Collec>on of name-value pairs
Names are strings, values can be anything
Proper>es and methods can be added at run>me

Objects can inherit other objects

Object Literal
var
var
var
var

mystring = "hello!";
myarray = ["element1", "element2"];
circle1 = {radius: 9, getArea : someFunction };
circle2 = {
radius: 9,
getRadius: function() {
return this.radius;
}

No Classes!
One of the simplest way to create object
var obj = new Object();
obj.x = 10;
obj.y = 12;
obj.method = function() { }

This adds dynamically two proper>es to the


obj object!
Object is built in data type

Class
To dene a class, dene a func>on
function Foo() {
this.x = 1;
this.y = 1;

var obj = new Foo();


Internally a Object is created

Example
function Circle(radius)
{
this.radius = radius;
this.getArea = function()
{
return (this.radius * this.radius) * Math.PI;
};
}
var myobj = new Circle(5);
document.write(myobj.getArea());

About Namespaces
Avoid pollu>ng global scope
Use namespaces!
Helps avoid clashes between your code and third-
party libraries

Namespaces dont have dedicated syntax


built into the language
Its possible to get same benets by crea>ng
single global object and add all other objects
and func>ons to this object

Example about Namespaces


"use strict";
// If first operand is truthy, then the result is
// first operand, else the result is second operand
// By convention namespaces are written in capitals
var MYSPACE = MYSPACE || {};
MYSPACE.Dog = function (name) {
this.name = name;
this.getName = function () {
return name;
};
};

var spot = new MYSPACE.Dog("Spot");


print(spot.getName());

Arrays
Arrays in JS are dynamic, content can be
added and removed
Arrays are also objects (Array class inherit
Object)
concat(), join(), pop(), push(), slice(), sort(), splice()

Example
"use strict";
var array1 = []; // or new Array()
var array2 = ['a', 'b', 'c'];
print(array2.length);
delete array2[1];
for(var i = 0; i<array2.length; i++) {
print(array2[i]);
}

Func>ons
Every func>on in JS is Func>on object
Can be passed as arguments
Can store name / value pairs
Can be anonymous or named

Usage (Dont use this, its not ecient)


var myfunction = new Function("a","b",
"return a+b;");
print(myfunction(3,3));

Only func>ons have scope, regular {blocks) dont


Inner func>on can have access to outer func>ons
proper>es and parameters

Func>on Arguments
The arguments object is a local object
available within all func>ons
Each func>on has access to special parameter
called arguments
Contains the func<on arguments

Its an array like object (but not an array)


Only arguments.length available

Example
"use strict";
function myConcat(separator) {
var result = "";
// iterate through non-separator arguments
for (var i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
// returns "red, orange, blue, "
print(myConcat(", ", "red", "orange", "blue"));
// returns "elephant; giraffe; lion; cheetah; "
print(myConcat("; ", "elephant", "giraffe", "lion", "cheetah"));
// returns "sage. basil. oregano. pepper. parsley. "
print(myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley"));

Func>onal Scoping
"use strict";
function init() {
// local variable name
var name = "Hello World";
// inner function
function displayName() {
// uses outer functions variable
print(name);
}
displayName();
}
init();

Returning a Inner Func>on


"use strict";
function makeFunc() {
var name = "Hello World";
function displayName() {
print(name);
}
return displayName;
}
// Is Hello World printed?
var myFunc = makeFunc();
myFunc();

About Closures
myFunc is a closure
Special kind of object that combines
A func>on
Environment in which func>on was created
Environment consists of any local variables that were
in-scope at the >me closure was created
myFunc is a closure that has displayName and name

Private members with Closures


"use strict";
function getPerson(name) {
var privateMember = "hello world!", obj;
obj = {
shout: function () {
print(name + " shouts " + privateMember);
},
say: function () {
print(name + " say " + privateMember);
}
};
return obj;
};
var person = getPerson("Jack");
// Does not work!
print(person.privateMember);
person.shout();
person.say();

Private methods with Closures


"use strict";
var person = (function(name) {
var privateMember = "hello world!", obj;
obj = {
setName: function(myName) {
name = myName;
},
shout: function () {
print(name + " shouts " + privateMember);
},
say: function () {
print(name + " say " + privateMember);
}
};
return obj;
})();
person.setName("Jack");
person.shout();
person.say();

function foo() {
// adds prop to global object
this.prop = 12;
}

this

var obj = {
method: function() {
// goes to obj
this.prop = 12;
}
};
obj.method();
function Dog(name) {
// Refers to object being created!
this.name = name;
this.sayHello = function() {
print(this.name + " says hello!");
};
}
var dog = new Dog("Spot");
dog.sayHello();

EXERCISE 5

INHERITANCE

About Inheritance
Code reuse is important
Inheritance can help

JavaScript does not have classes, so no special


keyword for extending
This can be very confusing for Java/C# developers
Objects inherit objects

Understanding JS Inheritance
JS is not class based, its prototype-based!
Object inherit from another object
JS contains syntax and features that make it
seem class based

Understanding Prototypes
Prototype is an object from which other
objects inherit proper>es
Any object can be a prototype
Every object has internal __proto__ property

Example
var parent = {
method1: function() { print("A"); }
}
var child = {
__proto__: parent,
method2: function() { print("B"); }
}
// If method1 is not found in child, look it from
// prototype!
child.method1(); // A
child.method2(); // B

__proto__
__proto__ is depricated and should not be
used (but it works)
To get the prototype, use
Object.getPrototypeOf(object)
Its read only!

How to set?
Proposal: Object.setPrototypeOf(obj, prototype)

Not possible to change the __proto__ ..!

Func>on Object
When wri>ng
function Animal() { }

Lot of things happens!


Two objects created:
1) Animal
2) Animal.prototype

Animal.prototype has a property constructor, that


points to Animal

Func>on Object
// This is just a function. Dog is Function object!
function Dog (name) {
this.name = (name);
}
var spot = new Dog("Spot");
// true
print(spot instanceof Object);
// true
print(Dog instanceof Function);
// true
print(Dog instanceof Object);

Func>on Object
function sum1(a, b) {
return a + b;
}
// =>
var sum2 = new Function("a","b", "return a+b;");
print(sum1(2,2));
// 4
print(sum2(2,2));
// 4
print(sum2.length); // number of args = 2
print(sum2.toString());

The new Operator


function Person() {
this.name = Jack;
}
// Normal function call
Person();
// Object creation
var p = new Person();

Example
function Cat() { }
// c.__proto__ points to Cat.prototype!
var c = new Cat();
// true
print(c.__proto__ === Cat.prototype);
// c inherites Cat.prototype!
Cat.prototype.age = 12;
// 12!
print(c.age);

Example
function Cat() { this.name = "Jack";
var c = new Cat();

// true
print(c.__proto__ === Cat.prototype);
// c inherites Cat.prototype! Let's add stuff.
Cat.prototype.age = 12;
Cat.prototype.saySomething = function() {
print(this.name + ": hello!");
}
// 12!
print(c.age);
// "Jack: hello!"
c.saySomething();

/** PERSON **/


function Person() { }
var jack = new Person();
// jack inherites Person.prototype!
print(jack.__proto__ === Person.prototype);
Person.prototype.age = 18;
print(jack.age); // 18;
//** STUDENT **/
function Student() { }
// Let's now change the prototype of Student.
// Now Student.prototype points to Person.
var temp = new Person();
Student.prototype = temp;
var tina = new Student();
// tina inherites Student.prototype.. which is now temp!
print(tina.__proto__ === Student.prototype); // true
print(tina.__proto__ === temp);
// true
// Now tina inherites Student.prototype, which is
// Person object, which inherites the Person.prototype..
print(tina.age);

// 18!

Example
/** Person **/
function Person() {
this.name = "Jack";
}
// Adding functionality to the prototype..
Person.prototype.say = function() {
print(this.name + : hello!");
}
/** Student **/
function Student() { }
// Inheritance
Student.prototype = new Person();
/** Test **/
var student = new Student();
student.say(); // Jack: Hello

Person.prototype
say()
new Person()
name = Jack
__proto__

Example
/** Person **/
function Person() {
this.name = "Jack";
}
// Adding functionality to the prototype.. What is this??
Person.prototype.say = function() {
print(this.name + : hello!");
}
/** Student **/
function Student() { }
// Inheritance
Student.prototype = new Person();
/** Test **/
var student = new Student();
student.say(); // Jack: Hello

Person.prototype
say()
new Person()
name = Jack
__proto__
new Student()
__proto__

Func>on Object
Every func>on in JS is a Func>on object
When
var spot = new Dog(spot);

Then spots __proto__ points to


Dog.prototype!
If a property cannot be found in an object, it
is searched for in that object's prototype.

Example
// here's the constructor:
function Point() { }
var a = new Point();
print (a.x); // undefined
// set up the prototype object to have some values:
Point.prototype = { x: 10, y: 20 };
// or you could do this:
Point.prototype.z = 30;
// make a new Point object
// (a object gets an implicit reference to Point.prototype object)
var a = new Point();
// Since a does not hold a property, let's look it from Point.prototype
print (a.x);

Example
// here's the constructor:
function Point() {
this.x = 10;
this.y = 20;
}
// set up the prototype object to have some values:
Point.prototype.z = 40;
// make a new Point object
// (a object gets an implicit reference to Point.prototype object)
var a = new Point();
// Since a does not hold a property, let's look it from Point.prototype
print (a.z);

//** POINT **
function Point() {
}
// set up the prototype object to have some values:
Point.prototype = { x: 10, y: 20 };
/** PIXEL **/
function Pixel() {
}
Pixel.prototype = new Point();
Pixel.prototype.color = "red";
// make a new Point object
// (a object gets an implicit reference to Point.prototype object)
var a = new Pixel();
var b = new Pixel();
a.color = "blue";
// Since a does not hold a property, let's look it from Point.prototype
print (a.color);
print (b.color);

About constructors
Prototype proper>es of Func>ons have a
constructor property:
var dog = new Dog();
dog.constructor == Dog; // TRUE

This will break when doing inheritance!

/** Person **/


function Person() {
}
Person.prototype.name = "Jack";
/** Student **/
function Student() {
this.id = "12345";
}
// Inheritance
Student.prototype = new Person();
Student.prototype.id = "12345";
/** Test **/
var student = new Student();
student.age = 22;
print(student.age)
print(student.name);
print(student.id);
var person = new Person();
print(person.constructor === Person);

// TRUE

var student = new Student();


print(student.constructor === Student); // FALSE

/** Person **/


function Person() {
}
Person.prototype.name = "Jack";
/** Student **/
function Student() {
this.id = "12345";
}
// Inheritance
Student.prototype = new Person();
Student.prototype.id = "12345";
// FIX
Student.prototype.constructor = Student;
/** Test **/
var student = new Student();
student.age = 22;
print(student.age)
print(student.name);
print(student.id);
var person = new Person();
print(person.constructor === Person);

// TRUE

var student = new Student();


print(student.constructor === Student); // FALSE

Inheritance: Prototypal
In EcmaScript 5 a protypal inheritance pa?ern
is part of the language
var child = Object.create(parent);

The create-func>on
function create(o) {
function F() {}
f.prototype = o;
return new F();
}

Example
function Point(x,y) {
this.x = x;
this.y = y;
}
var pixel = Object.create(new Point(12,0));
pixel.color = "red";
print(pixel.x);
print(pixel.color);

EXERCISE 6

JS LIBRARIES

Intro
Number of open source JS libraries
Assist frequent JS programming tasks
Hide browser dierences

Lot of possibili>es
Google Web Toolkit
JQuery
AngularJS
YUI3 (not developed anymore)
Modernizr

h?p://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks

JQuery
Mo>va>on
Simple things may require lot of coding
Common browsers are dierent and
implementa>on varies

Solu>on, use a framework


jQuery is a fast and concise JavaScript Library that
simplies HTML document traversing, event
handling, anima>ng, and Ajax interac>ons for
rapid web development.

How?
Download JQuery le (h?p://jquery.com/)
h?p://code.jquery.com/jquery-1.8.3.min.js

Make your (x)html page and reference to the


le in script block
Make your code and use JQuery func>ons!

<script type="text/javascript" src="jquery.js"></script>


<script type="text/javascript">
//<![CDATA[
// When document is ready to be manipulated
jQuery(document).ready( pageReadyToBeManipulated );
function pageReadyToBeManipulated() {
// If link is clicked
jQuery("a").click( linkClick );
}
function linkClick(event) {
alert("Thanks for visiting!");
// Prevent the default action
event.preventDefault();
}
//]]>
</script>

Some Basic Syntax


JQuery can be used in two ways:
JQuery()
Or
$()

$ is an alias to JQuery()! $ more commonly


used

<script type="text/javascript" src="jquery.js"></script>


<script type="text/javascript">
//<![CDATA[
// When document is ready to be manipulated
$(document).ready( pageReadyToBeManipulated );
function pageReadyToBeManipulated() {
// If link is clicked
$("a").click( linkClick );
}
function linkClick(event) {
alert("Thanks for visiting!");
// Prevent the default action
event.preventDefault();
}
//]]>
</script>

// USING ANONYMOUS FUNCTIONS


<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
//<![CDATA[
$(document).ready(function(){
$("a").click(function(event){
alert("Thanks for visiting!");
event.preventDefault();
});
});
//]]>
</script>

// EVEN SHORTER SYNTAX, FORGET THE DOCUMENT PARAMETER


<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
//<![CDATA[
$().ready(function(){
$("a").click(function(event){
alert("Thanks for visiting!");
event.preventDefault();
});
});
//]]>
</script>

Ge?ers in the Tradi>onal Way


getElementsById
getElementsByTagName
getAttribute

JQuery and Selectors


Select all h1 elements
$(h1)

Select the rst one


$(h1)[0]

Add contents
$(????)[0].innerHTML = hello!;

Lot of dierent selectors


h?p://api.jquery.com/category/selectors/

Crea>ng Elements in Tradi>onal Way

createElement
createTextNode
setAttribute
appendChild
removeChild

JQuery Insert
$().ready(function(){
$("a").click(function(event){
// Insert the new element after element with id here
$("<p>New Element</p>").insertAfter("#here");
event.preventDefault();
});
});

Manipula>on Func>ons

.addClass()
.amer()
.append()
.css()

See: h?p://api.jquery.com/category/
manipula>on/

EXERCISE 7

ANGULARJS

Angular JS
Single Page App Framework for JavaScript
Implements client-side Model-View-Whatever
pa?ern

Some call it MVC, some MVVM, it does not ma?er:


Separa<on of presenta>on from business logic and
presenta<on state

No direct DOM manipula>on, less code


Support for all major browsers
Supported by Google
Large and fast growing community

First Example Template


Direc>ve

Template

<!DOCTYPE html>
<html ng-app>
<head>
Download this le from:
<title>
https://angularjs.org/
Title
</title>
<meta charset="UTF-8" />
<style media="screen"></style>
<script src="angular.min.js"></script>
</head>
<body>
Direc>ve
<!-- initialize the app -->
<div>
<!-- store the value of input field into a variable name -->
<p>Name: <input type="text" ng-model="name"></p>
<!-- display the variable name inside (innerHTML) of p -->
<p ng-bind="name"></p>
</div>
</body>
</html>

Basic Concepts
1) Templates
HTML with addi>onal markup, direc>ves,
expressions, lters ...

2) Direc<ves
Extend HTML using ng-app, ng-bind, ng-model

3) Filters
Filter the output: filter, orderBy, uppercase

4) Data Binding
Bind model to view using expressions {{ }}

Lot of Built in Direc>ves

ngApp
ngClick
ngController
ngModel
ngRepeat
ngSubmit

ngDblClick
ngMouseEnter
ngMouseMove
ngMouseLeave
ngKeyDown
ngForm

2) Expressions
Angular expressions are JavaScript-like code
snippets that are usually placed in bindings
{{ expression }}.

Valid Expressions
{{ 1 + 2 }}
{{ a + b }}
{{ items[index] }}

Control ow (loops, if) are not supported!


You can use lters to format or lter data

Example
<!DOCTYPE html>
<html ng-app>
<head>
<title>Title</title>
Direc>ve
<meta charset="UTF-8" />
<style media="screen"></style>
<script src="../angular.min.js"></script>
</head>
<body>
<div>
<p>Number 1: <input type="number" ng-model="number1"></p>
<p>Number 2: <input type="number" ng-model="number2"></p>
<!-- expression -->
<p>{{ number1 + number2 }}</p>
</div>
</body>
Expression
</html>

Direc>ve

ng-init and ng-repeat direc>ves


<html data-ng-app="">
<head>
<title>Title</title>
<meta charset="UTF-8" />
<script src="../angular.min.js" type="text/javascript">
</script>
</head>
<body>
<div data-ng-init="names = ['Jack', 'John', 'Tina']">
<h1>Cool loop!</h1>
<ul>
<li data-ng-repeat="name in names">{{ name }}</li>
</ul>
</div>
</body>
</html>

3) Filter
With lter, you can format or lter the output
Formanng
currency, number, date, lowercase,
uppercase

Filtering
filter, limitTo

Other
orderBy, json

Using Filters - Example


<!DOCTYPE html>
<html data-ng-app="">
<head>
<title>Title</title>
<meta charset="UTF-8">
<script src="../angular.min.js" type="text/javascript">
</script>
</head>
<body>
<div data-ng-init="customers = [{name:'jack'}, {name:'tina'}]">
<h1>Cool loop!</h1>
<ul>
<li data-ng-repeat="customer in customers | orderBy:'name'">
{{ customer.name | uppercase }}</li>
</ul>
</div>
</body>
</html>
Filter

Filter

Using Filters - Example


<!DOCTYPE html>
<html data-ng-app="">
<head>
<title>Title</title>
<meta charset="UTF-8">
<script src="../angular.min.js" type="text/javascript">
</script>
</head>
<body>
<div data-ng-init=
"customers = [{name:'jack'}, {name:'tina'}, {name:'john'}, {name:'donald'}]">
<h1>Customers</h1>
<ul>
<li data-ng-repeat="customer in customers | orderBy:'name' | filter:'john'">{{
customer.name | uppercase }}</li>
</ul>
</div>
</body>
</html>

Using Filters User Input Filters the Data


<!DOCTYPE html>
<html data-ng-app="">
<head>
<title>Title</title>
<meta charset="UTF-8">
<script src="../angular.min.js" type="text/javascript">
</script>
</head>
<body>
<div data-ng-init=
"customers = [{name:'jack'}, {name:'tina'}, {name:'john'}, {name:'donald'}]">
<h1>Customers</h1>
<input type="text" data-ng-model="userInput" />
<ul>
<li data-ng-repeat="customer in customers | orderBy:'name' | filter:userInput">{{
customer.name | uppercase }}</li>
</ul>
</div>
</body>
</html>

EXERCISE 8 + 9

VIEWS, CONTROLLERS, SCOPE

Model View - Controllers


Controllers provide the logic behind your app.
So use controller when you need logic behind
your UI

Use ng-controller to dene the controller


Controller is a JavaScript Object, created by
standard JS object constructor

View, Controller and Scope


View

(html fragment)

$scope

Controller

(view agnos>c!)
Model

$scope is an object that can be used


to communicate between
View and Controller

controller.js
// Angular will inject the $scope object, you don't have to
// worry about it! By using $scope, you can send data to
// view (html fragment)
function NumberCtrl ($scope) {
// $scope is bound to view, so communication
// to view is done using the $scope
$scope.number = 1;
$scope.showNumber = function showNumber() {
window.alert( "your number = " + $scope.number );
};
}

Warning, this will not work from AngularJS 1.3.


We will see later on how this is done using module

<!DOCTYPE html>
<html data-ng-app="">
<head>
<title>Title</title>
<meta charset="UTF-8" />
<style media="screen"></style>
<script src="../angular.min.js"></script>
<script src="controller.js"></script>

Dene the Controller


implemented in
controller.js

</head>
<body>
<div>
<div data-ng-controller="NumberCtrl">
<p>Number: <input type="number" ng-model="number"></p>
<p>Number = {{ number }}</p>
<button ng-click="showNumber()">Show Number</button>
</div>
</div>
</body>
</html>
Access $scope.number
Access

$scope.showNumber()

When to use Controllers


Use controllers
set up the ini>al state of $scope object
add behavior to the $scope object

Do not
Manipulate DOM (use data-binding, direc<ves)
Format input (use form controls)
Filter output (use lters)
Share code or state (use services)

MODULES, ROUTES, SERVICES

Modules
Module is an reusable container for dierent
features of your app
Controllers, services, lters, direc>ves...

All app controllers should belong to a


module!
More readability, global namespace clean

Modules can be loaded in any order


We can build our own lters and direc<ves!

Example: Own Filter


// declare a module
var myAppModule = angular.module('myApp', []);
// configure the module.
// in this example we will create a greeting filter
myAppModule.filter('greet', function() {
return function(name) {
return 'Hello, ' + name + '!';
};
});

HTML using the Filter


// We will use module myApp
<div ng-app="myApp">
<div>
{{ 'World' | greet }}
</div>
</div>

angular.module
The angular.module is a global place for
crea>ng, registering and retrieving Angular
modules
Crea>ng a new module
var myModule = angular.module('myMod', []);

The second argument ([]) denes dependent


modules which modules should be loaded
rst before this

Template for Controllers


// Create new module 'myApp' using angular.module method.
// The module is not dependent on any other module
var myModule = angular.module('myModule',
[]);
myModule.controller('MyCtrl', function ($scope) {
// Your controller code here!
});

Crea>ng a Controller in Module


var myModule = angular.module('myModule',
[]);
myModule.controller('MyCtrl', function ($scope) {
var model = { "firstname": "Jack",
"lastname": "Smith" };
$scope.model = model;
$scope.click = function() {
alert($scope.model.firstname);
};
});

<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="UTF-8" />
<style media="screen"></style>
<script src="../angular.min.js"></script>
<script src="mymodule.js"></script>

This is now the model


object from MyCtrl. Model
object is shared with view
and controller

</head>
<body>
<div ng-app="myModule"
<div ng-controller="MyCtrl">
<p>Firstname: <input type="text" ng-model="model.firstname"></p>
<p>Lastname: <input type="text" ng-model="model.lastname"></p>
<p>{{model.firstname + " " + model.lastname}}</p>
<button ng-click="click()">Show First name</button>
</div>
</div>
</body>
</html>

EXERCISE 10 - 11

AMD

AMD
JavaScript does not have "classes" or "packages" or "import"
Asynchronous Module Deni<on (AMD) is a JS specica>on
that denes API for dening code in modules
Load smaller JS les, only when needed
Allow developers dene dependencies
Encapsula>on
Specica>on is implemented by RequireJS and ScriptManJS
Specica>on:
https://github.com/amdjs/amdjs-api/blob/master/AMD.md

Dierent JS libraries support AMD spec


RequireJS, curl, lsjs and Dojo

Problem
Gezng mul>ple les onto a page is to include
script tags
<script src="file1.js"></script>
<script src="file2.js"></script>
<script src="file3.js"></script>

All is loaded to global namespace


Some scripts depend each other -> order is
important.
Download >me!

Dening Modules
Use define func>on of RequireJS
Each module in separate le (.js)
File name will be a module ID.

Modules are dependent on others


Module declares a list of other modules for
dependency
No more includes in right order, modules interact with
each other without global namespace

Module is dened as "factory"


Can be object or func>on that returns a value

Dening and using Modules


Dierent modules

Using module

// modules/number.js
define('numberModule', 7);

require(['album'], function(album) {
console.log(album.title);
});

// modules/album.js
define('album', {
title: 'Haavemaa',
artist: 'Tauski Peltonen',
year: 1997
});
// modules/counter.js
define('counter', function() {
var counter = 0;
return {
increment: function() {
counter++;
},
getValue: function() {
return counter;
}
};
});

RequireJS: How to Use?


1. Download le script for Browser or
Command line
http://requirejs.org/docs/start.html#get

2. Add RequireJS to your web page (if using


browser)
<script data-main="scripts/main" src="scripts/require.js">
</script>

3. Use predened directory structure

<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="UTF-8" />
<style media="screen"></style>
<!-Define single entry-point to your app.
data-main attribute tells require.js to load
scripts/main.js after require.js loads.
js is appended by default main -> main.js

www/index.html
scripts/require.js
main.js
modules/module1.js
module2.js
-->
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
<body>
</body>
</html>

main.js
// Load modules and use them
// require() function has two arguments
//
1) array of dependencies
//
2) callback function to execute once all the dependencies have loaded.
//
function arguments are the specified dependencies!
require(['modules/number', 'modules/counter', 'modules/album'], function(number, counter,
album){
// do something with the loaded modules
console.log(number)
console.log(album.title)
counter.increment();
counter.increment();
console.log(counter.getValue())
});

main.js
// Load modules and use them
// require() function has two arguments
//
1) array of dependencies
//
2) callback function to execute once all the dependencies have loaded.
//
function arguments are the specified dependencies!
require(['modules/module1', 'modules/module2'], function(Module1, Module2){
// do something with the loaded modules
var module1 = new Module1();
var module2 = new Module2();
console.log(module1.getName())
console.log(module2.getName())
});

modules/module1+2.js
module1.js

module2.js

define([], function () {
function returnedModule() {
var name = 'Module 1';
this.getName = function () {
return name;
}
};

define(['modules/module1'], function (Module1) {


var module1 = new Module1()
function returnedModule() {
var name = 'Module 2: ';
this.getName = function () {
return name + module1.getName();
}
};

return returnedModule;
});

return returnedModule;
});

JQuery and RequireJS


JQuery is AMD compa>ble
Download jquery le and name it as
"jquery.js"
Amer this you can use it like any other
module!

JQuery and RequireJS


require(['jquery'], function(jquery){
// do something with the loaded modules
jquery( "#myform" ).submit(function( event ) {
...
event.preventDefault();
});
});

EXERCISE 12

LIBRARY DESIGN

Designing Libraries
Designing JS libraries are hard
Dynamic nature of the language
Dicult to keep things truly private / sandboxed

Lets look at some general principals about


designing libraries
When possible, see how exis>ng libraries have
done things..

API Design
Consistent
Easy to learn when each module have a similar
API

Clean
Well documented
Consider plugin architecture

Sandbox pa?ern

Anonymous Closures
Create anonymous func>on and execute it
immediately

(function () {
// ... all vars and functions are in this
// scope only
// still maintains access to all globals
}());

Dening Modules
Closures provide handy way of keeping
module code sandboxed
Less pollu>on to global namespace
Avoid modules breaking each other
Modules can access globals

In-depth tutorial
h?p://www.adequatelygood.com/2010/3/
JavaScript-Module-Pa?ern-In-Depth

Dening Modules
var MODULE1 = function() {
// Place module implementation here.
// All vars and functions declared here are private to
// this scope.
// Can access globals if needed.
}();

var MODULE1 = function() {


// Private stuff (notice the single var pattern)
var privateVar1 = "",
privateVar2 = "moi",
privateFunc1 = function() { /* ... */ },
privateFunc2 = function() { /* ... */ };
function privateFunc3() { /* ... */ }

// Public stuff exported as part of an object. Due to the


// closure, the public functions can access all the private
// vars and functions as well.
return {
foo: function() { return "Hello World"; },
bar: function() { privateVar1 = "Hello!" },
publicVar1: "",
publicVar2: 12
}
}();
console.log(MODULE1.foo());
console.log(MODULE1.publicVar2);
console.log(MODULE1.privateVar1);

// Hello World
// 12
undefined

About Globals
// - Code should not rely on certain global objects to
// be available...
// - Local variables are more efficient
//
- Shorter lookup paths for objects
// - Can be minified to reduce file size
var MODULE2 = function(globalWindowObject, documentObject) {
var width = globalWindowObject.innerWidth;
return { prop: width };
}(this, this.document);
console.log(MODULE2.prop);

UNIT TESTING

Test-driven development
Each new feature begins with wri<ng a test!
Test will fail since the produc>on code does not
exist yet

Write the code


Run automated tests to see if if test cases
pass
Automated tests?
We need a framework

JS Unit Tes>ng Frameworks


Lot of op>ons
JSUnit, YUI Test, QUnit, Google Closure Tools

QUnit
QUnit is a JS unit tes>ng framework
Can be used in client and also in server (Node.js)
Was originally developed as part of JQuery
Extracted its own project and became known as
"QUnit"

How?
Download qunit.js and qunit.css
Write a simple HTML page to run the tests
Write the tests

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="qunit-1.18.0.css">
<script src="qunit-1.18.0.js"></script>
</head>
<body>
<div id="qunit"></div>
<script type="text/javascript">
function calculate(a, b) {
return a + b;
}
QUnit.test( "calculate test", function(assert) {
assert.ok( calculate(5,5) === 10, "Ok!" );
assert.ok( calculate(5,0) === 5, "Ok!" );
assert.ok( calculate(-5,5) === 0, "OK!" );
});
</script>
</body>
</html>

Three Asser>ons
Basic
ok( boolean [, message]);

If actual == expected
equal( actual, expected [, message]);

if actual === expected


deepEqual( actual, expected [, message));

Other
http://qunitjs.com/cookbook/#automatingunit-testing

EXERCISE 13

JAVASCRIPT OPTIMIZING

Brief look of Op>mizing


Script deployment
Code op>miza>on
Loops, strings, DOM access and data access

Mul>threading with Web Workers


Performance tools

Script Deployment
Group to have as few les as possible!
Loading one le is much be?er than ten les,
HTTP overhead!

Can be done at build >me or at run >me


Run >me grouping
src=h?p://site.com/combine?foo.js&bar.js

Script Deployment
Minify or gzip your scripts (for example:
closure compiler)
Reduces the size
Code gets obfuscated
Some older browsers do not support gzipped les

Code Op>miza>on
Do not op<mize your code!
Unreadable code
Concentrate on maintainable

If you have to op<mize


Concentrate code that executed most omen

Check string and DOM opera<ons


These are slow in JS!

Data and Property Access


Data and property access may be expensive
document.getElementById(a).appendChild(child1);
document.getElementById(a).appendChild(child2);

Cache frequently used objects


var x = document.getElementById(a);
x.appendChild(child1);
x.appendChild(child2);

Strings
Avoid
mystring += rst + second
Creates temporary string in memory

Use
mystring += rst;
mystring += second;

Or use Array.join()
myArray = [rst, second];
var str = myArray.join();

Loops
Dont use for-in in arrays, requires addi>onal
property lookups
Cache variables!
var len = myarray.length;
var element =
document.getElementById(id);
for(var i = 0; i<len; i++) {
// Use element

Web Workers
Web worker is a JS way of doing things in background.
W3C recommenda:on.
API that allows Web applica>on authors to spawn
background workers running scripts in parallel to their
main page.
Web worker spec is separate spec from HTML5

Bring mul>threading to your app

Heavy calcula>ons or long-running tasks in the background


Keep UI responsive

No need to use Web Workers in AJAX (mul>-threading


on by default)
Cannot manipulate UI (DOM)!

<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script>

function sayHello(){
var worker = new Worker('worker.js');
worker.onmessage = function (event) {
alert("Completed " + event.data + " iterations" );
};
worker.postMessage(50000);
}
</script>
</head>
<body>
<input type="button" onclick="sayHello();" value="Say Hello"/>
</body>
</html>

onmessage = function(event) {
var number = event.data;
for (var i = 0; i <= number; i += 1){
var j = i;
}
postMessage(j);
}

Check Web Worker support


if (typeof(Worker)!=="undefined) {
}

EXERCISE 14

Das könnte Ihnen auch gefallen