JavaScript Primer

Preview:

DESCRIPTION

The second-half of the php|tek 2012 tutorial session "HTML5 and JavaScript"

Citation preview

HTML5 and JavaScriptPart Deux

Thursday, July 5, 12

Daniel Cousineau@dcousineau

Thursday, July 5, 12

History

Thursday, July 5, 12

MochaLiveScript

JavaScript

Brendan EichCTO, Mozilla Corp.

April 1995

Thursday, July 5, 12

JavaScriptECMAScript

ActionScript

JScript

Thursday, July 5, 12

Basics

Thursday, July 5, 12

Data Types•number

• string

•boolean

•object

•null

•NaN

•undefined

Thursday, July 5, 12

Strings

•Are Objects, have methods

Thursday, July 5, 12

"Foo" + "Bar"; //"FooBar"

var str = "Lorem Ipsum Dolor Sit Amet";

str.toLowerCase(); //"lorem ipsum dolor sit amet"str.toUpperCase(); //"LOREM IPSUM DOLOR SIT AMET"str.split(" "); //["Lorem", "Ispum", "Dolor", "Sit", "Amet"]str.substring(6,9); //"Ips"

new String("Lorem Ipsum Dolor Sit Amet") == str; //true

Strings

Thursday, July 5, 12

parseInt("56"); //56parseInt("42.567"); //42parseInt("asdf"); //NaNparseInt("5a6"); //5parseFloat("24.68"); //24.68parseFloat("asdf"); //NaNparseFloat("24a"); //24

String to Number

Thursday, July 5, 12

Objects

• “Dictionary” / “Associative Array”

•Key: Value or 'Key': Value

•Without ': A-Z0-9 only

•Does not keep intrinsic ordering

•Accessed keys using . (dot) or [] notation

Thursday, July 5, 12

var object = { foo: 'value', 'complex key': 0, bar: { nested: true }};

object.foo; //'value'object.['complex key']; //0object.bar.nested; //trueobject.bar['nested']; //trueobject['bar'].nested; //trueobject['bar']['nested']; //true

Objects

Thursday, July 5, 12

in or hasOwnProperty()

•Tough call:

•.hasOwnProperty() more consistent

•in checks inherited properties

•Used in for loop

Thursday, July 5, 12

var test = { foo: 'value', bar: 'value', baz: 'value'}

for (var key in test) { console.log(key + ": " + test[key]);}

//PRINTS://foo: value//bar: value//baz: value

in

Thursday, July 5, 12

Arrays

•Special object

•Numerical keys only

•Keeps intrinsic ordering

•Short ([]) and Long (new Array()) syntax

Thursday, July 5, 12

var arrayShort = [ 'one', 'two'];arrayShort[2] = 'three';

var arrayLong = new Array();arrayLong[0] = 'one';arrayLong[1] = 'two';arrayLong[2] = 'three';

//arrayShort: ["one", "two", "three"]//arrayLong: ["one", "two", "three"]

Arrays

Thursday, July 5, 12

var arr = [1,2,3,4,6];

arr.indexOf(2); //1arr.join(':'); //"1:2:3:4:6"arr.pop(); //6 //[1,2,3,4]arr.push(7); //5 //[1,2,3,4,7]arr.reverse(); //[7,4,3,2,1]arr.shift(); //1//[2,3,4,7]arr.unshift(8); //5//[8,2,3,4,7]arr.slice(1); //[2,3,4,7]arr.slice(1,3); //[2,3]arr.slice(-3); //[3,4,7]arr.slice(-3,-1); //[3,4]

Arrays

Thursday, July 5, 12

var arr1 = [1,2,3];var arr2 = [3,4,5];

arr1.concat(arr2); //[1,2,3,3,4,5]

Arrays

Thursday, July 5, 12

delete

•Removes element from an object

• “Removes element from an array”

•Not really, just sets it to undefined

Thursday, July 5, 12

Functions

•Are Objects as well

• “Elevated”

•You can use a named function before it is defined in code

•Function definitions are elevated to the top

Thursday, July 5, 12

function Foo() { //...}

Foo(); //validBar(); //valid

function Bar() { //...}

Functions

Thursday, July 5, 12

function Foo() { }

Foo.bar = "value";

'bar' in Foo; //trueFoo.bar == "value"; //true

Functions

Thursday, July 5, 12

Function Arguments

•No way to assign default arguments

•But arguments are not required

• If an argument is not specified, it is set to undefined

Thursday, July 5, 12

arguments

•A special variable found inside a function

•A not-quite array object containing all the function arguments

Thursday, July 5, 12

function sum() { var x = 0; for (var i = 0; i < arguments.length; ++i) { x += arguments[i]; } return x;}sum(1, 2, 3); //6

arguments

Thursday, July 5, 12

typeof

•Determines a variables type

•Returns a string

Thursday, July 5, 12

typeof true; //"boolean"typeof 12; //"number"typeof "string"; //"string"typeof []; //"object"typeof {}; //"object"typeof NaN; //"number"typeof null; //"object"typeof undefined; //"undefined"

function Foo() {}typeof Foo; //"function"

typeof

Thursday, July 5, 12

Comparison

•a == b / a != b

•A and B compared by value alone

•1 == “1” evaluates to true

•a === b / a !== b

•A and B compared by value and by type

•1 === “1” evaluates to false

Thursday, July 5, 12

window, document•Built in, global, Objects

•window

•Provides access to the browser window

•The “global” object: foo === window.foo

•Things like window.location.href, etc

•document

•Provides access to the current DOMThursday, July 5, 12

Closures

Thursday, July 5, 12

Closures

•First-Class

•Can assign functions to variables, pass as arguments and return as values

•Anonymous

•Not required to have a name

•A function that “closes over” variables defined outside itself

Thursday, July 5, 12

function Foo() { var count = 0; return function() { count = count + 1; return count; };}

var bar = Foo();

bar(); //1bar(); //2bar(); //3

Closures

Thursday, July 5, 12

function createAdder(amount) { return function(input) { return input + amount; };}

var add2 = createAdder(2);

add2(2); //4add2(8); //10

var add3 = createAdder(3);

add3(3); //6add3(7); //10

Closures

Thursday, July 5, 12

(function(exports, undefined){ //ALL your code here var localVar = "bar" globalVar = "baz"; exports.foo = "bat";})(window);

alert(localVar); //erroralert(globalVar); //"baz"alert(window.globalVar); //"baz"alert(foo); //"bat"alert(window.foo); //"bat"

Module Pattern

BEWARE: export (singular) is a reserved word in SafariThursday, July 5, 12

Scoping

Thursday, July 5, 12

Global & Local

•Functions are the only way to create new scopes

•Variables defined with var are local

•Variables defined without var are global

•Global variables are members of window

Thursday, July 5, 12

var outerScope = 10;var outerScope2 = 10;

function Foo() { var outerScope = 20; var innerScope = 20; globalVariable = 30; outerScope2 = 40;}

Foo();

alert(outerScope); //10alert(outerScope2); //40alert(innerScope); //erroralert(globalVariable); //30

Global & Local

Thursday, July 5, 12

function Foo() { var baz = 1; function Bar() { return baz; } return Bar();}

Foo(); //1

Lexical Scopingfunction Foo() { var baz = 1; return Bar();}

function Bar() { return baz;}

Foo(); //baz is not defined

Thursday, July 5, 12

Named functions are parsed and made available before general evaluation (thus “hoisted” to the top of the file).

Anonymous functions, or functions assigned to variables, require evaluation before they become available

foo(); //called foo!

function foo() { console.log('called foo!');}

foo(); //called foo!

bar(); //undefined is not a function

var bar = function() { console.log('called bar!');}

bar(); //called bar!

Hoisting

Thursday, July 5, 12

function makeAdder(a) { return function(b) { return a+b; }}

var two = makeAdder(2);two(1); //3two(2); //4two(3); //5

Practical: Currying

Thursday, July 5, 12

this

Thursday, July 5, 12

this

•Trips everyone up

•Special variable used within a function

•Refers to the “contextual object”

•Changes based on where a function executes

Thursday, July 5, 12

var Foo = { bar: "bar", baz: function() { return this.bar; }};

Foo.baz(); //"bar"

Foo.bar = "bat";Foo.baz(); //"bat"

var baz = Foo.baz;baz(); //undefined

this

Thursday, July 5, 12

var Foo = { bar: "bar", baz: function() { return this.bar; }};

Foo.bat = function() { return this.bar + "bat";};

Foo.bat(); //"barbat"

this

Thursday, July 5, 12

call & apply

•Methods in the function prototype

•Change the context in which a function executes!

Thursday, July 5, 12

var Foo = { bar: "bar", baz = function(param1, param2) { return this.bar + param1 + param2; }};

var Foo2 = { bar: "123"};

Foo.baz("baz", "bat"); //"barbazbat"

Foo.baz.apply(Foo2, "baz", "bat"); //"123bazbat"Foo.baz.call(Foo2, ["baz", "bat"]); //"123bazbat"

call & apply

Thursday, July 5, 12

function bind(func, context) { return function() { return func.call(context, arguments); }}

Practical: Binding

Thursday, July 5, 12

Exceptions

Thursday, July 5, 12

Exceptions

•All errors are thrown

•Classic try...catch...finally blocks

Thursday, July 5, 12

try { funcDoesNotExist();} catch (e) { alert(e); //ReferenceError: funcDoesNotExist is not defined} finally { //Always Executes}

Exceptions

Thursday, July 5, 12

function Foo() { throw new Error("Message");}

function Bar() { throw "Message";}

try { Foo();} catch (e) { e.message == "Message"; //true}

try { Bar();} catch (e) { e == "Message"; //true}

Exceptions

Thursday, July 5, 12

Prototype

Thursday, July 5, 12

OOP... Kinda...

•Almost no real difference between a dictionary and an object

•Named Functions double as object constructors

•Function objects contain a prototype dictionary that is copied to instance when using new

Thursday, July 5, 12

Foo‣ bar‣ prototype‣ baz‣ constructor‣ __proto__

function Foo() { //The "Constructor"}

Foo.bar = function() { //A "Static" Function}

Foo.prototype.baz = function() { //A "Method"};

OOP... Kinda...

Thursday, July 5, 12

instance‣ __proto__‣ baz‣ constructor‣ __proto__‣ ...

var instance = new Foo();

instance.baz(); //worksinstance.bar(); //error

Foo.bar(); //worksFoo.baz(); //errorFoo.prototype.baz(); //works

new

Thursday, July 5, 12

instance‣ bat‣ __proto__‣ baz‣ constructor‣ __proto__‣ ...

instance.bat = function() { /* ... */ }

instance.bat(); //works

Foo.bat(); //errorFoo.prototype.bat(); //error

new

Thursday, July 5, 12

function Foo(baz) { this.baz = baz;}

Foo.prototype.bar = function() { return this.baz;};

var foo1 = new Foo(1);var foo2 = new Foo(2);

foo1.bar(); //1foo2.bar(); //2

Foo.prototype.bar = function() { return this.baz * 2;};

foo1.bar(); //2foo2.bar(); //4

Overriding Prototype

Thursday, July 5, 12

Asynchronous

Thursday, July 5, 12

Asynchronous

• setTimeout, setInterval allow you to have code executing asynchronously while other code executes

Thursday, July 5, 12

var id = setInterval(function() { //Code to execute every 1000 milliseconds}, 1000);

//clearInterval(id); to stop

setInterval

Thursday, July 5, 12

var id = setTimeout(function() { //Code to execute after 1000 milliseconds have passed}, 1000);

//clearTimeout(id); to cancel

setTimeout

Thursday, July 5, 12

setInterval()

setTimeout()

Thursday, July 5, 12

setTimeout(function() { //Code to run in parallel //while the code after is //executed.}, 1);

//Code here will execute immediately//without waiting on the above

Nifty Trick

Thursday, July 5, 12

DOM

Thursday, July 5, 12

DOM

•Document Object Model

•API to interact with the HTML/XHTML document

Thursday, July 5, 12

Basic selection methods in native DOM

document .getElementById('foo');

document .getElementsByClassName('.bar');

document .getElementsByTagName('script');

DOM: Selection

Thursday, July 5, 12

Thursday, July 5, 12

var paragraph = document.createElement('p');var content = document.createTextNode("Lorem Ipsum");

paragraph.appendChild(content);paragraph.classList.add('my-class');

document.getElementsByTagName('body')[0].appendChild(paragraph);

DOM: Creation

Thursday, July 5, 12

Thursday, July 5, 12

Creates a script element, set its src and async properties

Insert the script before the first script tag in the body of the document

var script = document.createElement('script');script.src = "http://path.to/script.js";script.async = true;

var s = document .getElementsByTagName('script')[0];

s.parentNode .insertBefore(script, s);

Async Script Loading

Thursday, July 5, 12

DOM

https://developer.mozilla.org/en/Gecko_DOM_Reference

Thursday, July 5, 12

Debugging

Thursday, July 5, 12

Chrome/Safari Devel. Tools

Thursday, July 5, 12

Firefox FireBug

Thursday, July 5, 12

Console

•Provided by major browser vendors

•Useful for viewing logs, exceptions, real-time data dumping, and code execution within the current context

•Your best friend

•Though older IEs FREAK OUT when you leave it in, remove before deploy!

Thursday, July 5, 12

console

•Ditch alert(), this is your var_dump()

•console.log(arg1, arg2, ...)

•console.info Same as log

•console.warn Icon indicator

•console.error Stack trace

Thursday, July 5, 12

BEWARE

•console.log is not blocking

• In heavily asynchronous applications, sometimes value displayed is not value at the moment of the call

•Your if/else conditionals will work yet console.log will return something that should cause them to fail

Thursday, July 5, 12

Network

•Display all network requests via a gantt-like graph

•Shows browser-initiated (css, images, etc) and script initiated (ajax) alike

•Along with both request and response headers

Thursday, July 5, 12

Script

•Provides a familiar break-point debugging workflow

Thursday, July 5, 12

Coding Styles

Thursday, July 5, 12

Coding Styles

•Mostly your standard C based style techniques

•Special considerations

•Semi-colons? No semi-colons?

•Leading , ?

•Prototype Definition?

Thursday, July 5, 12

var dict = { foo: 'bar', baz: 'bat'};

var dict = { foo: 'bar' , baz: 'bat'};

Comma Style

Thursday, July 5, 12

var foo;var bar;var baz;

var foo , bar , baz;

var Declaration Style

Thursday, July 5, 12

function Foo() { }

Foo.prototype.bar = function(){ };

Prototype Stylefunction Foo() { }

Foo.prototype = { bar: function() { }}

Thursday, July 5, 12

Code Quality Tools

• JSLint http://www.jslint.com/

•By Crockford, extremely strict and inflexible. Code like Crockford!

• JSHint http://www.jshint.com/

•Fork, more flexible according to your own rules and preferences

Thursday, July 5, 12

Common Techniques

Thursday, July 5, 12

Grab global App dictionary, or create if not found

Add a function utility, is now globally accessible without fearing collision with other functioned similarly named

App = window.App || {};

App.utility = function() { //Globally available, no //conflicts};

Safe Extension

Thursday, July 5, 12

Immediately Invoked Function Expression

Function is defined then immediately invoked. Closest thing to a namespace/module system.

Prevents variable leakage into outer scopes

(function(exports){ exports.foo = function() { }; var bar = function() { };})(window);

foo(); //successbar(); //not found!

IIFE

Thursday, July 5, 12

Pro-Tip

•Create an application namespace as a dictionary in the global scope

•Add in any global level configuration values

Thursday, July 5, 12

JSON

Thursday, July 5, 12

JSON

Douglas CrockfordAwesome

2001

Thursday, July 5, 12

JSON• JavaScript Object Notation

•Serialization format that is basically JavaScript code minus comments

•Can be eval()’ed

•But don’t! Use JSON2.js or equivalent

•Minimal overhead compared to XML

•No parsers required, native mapping

Thursday, July 5, 12

{"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] }}}

JSON<menu id="file" value="File"> <popup> <menuitem value="New" onclick="CreateNewDoc()" /> <menuitem value="Open" onclick="OpenDoc()" /> <menuitem value="Close" onclick="CloseDoc()" /> </popup></menu>

Thursday, July 5, 12

BREAK HAMMER TIME

Thursday, July 5, 12

jQuery

Thursday, July 5, 12

jQuery

John ResigAuthor, jQuery

January 2006

Thursday, July 5, 12

jQuery

•Cross-browser JavaScript library

•Simplifies and normalizes DOM, AJAX, etc.

•Centers around using extended CSS selectors to grab an element(s)

Thursday, July 5, 12

Selectors

•Superset of CSS3 selectors

•Custom Pseudo-Classes

•Filters in jQuery parlance

Thursday, July 5, 12

Selectors

•$('selector') returns jQuery object for chaining purposes

•Chained methods will apply to all results if selector matches multiple elements

Thursday, July 5, 12

Finds all p tags that do not have the class special, and adds the class semi-special

$("p:not(.special)") .addClass("semi-special");

Selectors

Thursday, July 5, 12

Gets the value of the selected option in a select box

$('select option:selected').val();

Selectors

Thursday, July 5, 12

Tests matched element against selector, in this case the jQuery ‘visible’ selector

$('.foo').is(':visible');

Testing Elements

Thursday, July 5, 12

Custom Filters

• jQuery provides the ability to create custom filters

•:radio, :hidden, etc are custom filters provided by default

Thursday, July 5, 12

$("#foo") .html("<strong>bar</strong> baz");

jQuery<div id="foo"></div>

<div id="foo"> <strong>bar</strong> baz</div>

Thursday, July 5, 12

Chaining

•Most all jQuery methods are chain-able

• If $() returns > 1 element, methods invoked will apply to all matched

Thursday, July 5, 12

Find all ul with class first

Find elements of class foo that are children of the top level matched set

Apply the css style of color:red;

Pop the matching of .foo off the jQuery object

Find elements of class bar that are children of the top level matched set (ul.first)

Apply the css style of color:blue;

$('ul.first') .find('.foo') .css('color', 'red') .end().find('.bar') .css('color', 'blue') .end();

Chaining

Thursday, July 5, 12

Events

• jQuery wraps an event handling system

•Handles browser events, AJAX events, and custom events

Thursday, July 5, 12

$(document).ready(function() { //Only execute when the document fires //its onready event (page is done loading)});

$(document).bind('ready', function() { //Equivalent to the above});

$(function() { //Shortcut, equivalent to the above});

Events

Thursday, July 5, 12

$('img').hover(function(){ //Do something when user hovers over //any img tag});

Events

Thursday, July 5, 12

Events

•Event functions have the matched element from jQuery bound as this

Thursday, July 5, 12

Listen for click on a.foo

this will be the specific a.foo element that was clicked

$('a.foo').click(function(){ var $this = $(this) , href = $this.href(); //href will be the clicked //links href});

jQuery

Thursday, July 5, 12

Live Events

•Events using .bind are bound to the specific element at the specific point in time it was bound• New elements that match will not be included

•Using .on or .off produces a delegate listener that scans for bubbled events that match a selector• New elements that match said selector WILL be included

Thursday, July 5, 12

All a tags that exist at some point as a descendant of .grandparent will trigger this event on click

Any future a tags that are added as a descendant of .grandparent will trigger this event on click

$('.grandparent') .on('click', 'a', function(e){ var $target = $(e.target); //$target will *usually* //be the a tag, though //sometimes it will be a //nested tag });

Live Events

Thursday, July 5, 12

Create a Prototype object for example purposes, then create new instance.

The first click handler will fail. The keyword this will not be a reference to the instance of Foo as expected, but a reference to the matched DOM element that was clicked.

jQuery.proxy() will wrap your function such that further invocations will use the context you set for this

function Foo() {}

Foo.prototype.baz = function() {};Foo.prototype.bar = function() { this.baz();};

var instance = new Foo();

$('element').click(instance.bar);

$('element').click( jQuery.proxy( instance.bar, instance ););

Proxy

Thursday, July 5, 12

When .button is clicked, fade out img.preview over 600 milliseconds and then remove it from the DOM

$('.button').click(function(){ $('img.preview') .fadeOut(600, function() { $(this).remove(); });});

Animation

Thursday, July 5, 12

Animate the following attributes over the course of 5 seconds: opacity to 25% move to the right 50px toggle height

$('#book').animate({ opacity: 0.25, left: '+=50', height: 'toggle' }, 5000, function() { // Animation complete. });

animate

Thursday, July 5, 12

DOM Creation / Insertion

•Super easy! Provide html tag to $() and jQuery will create the element and return it wrapped in jQuery

•Second parameter is dictionary for properties

•Then use methods like .append() to insert

Thursday, July 5, 12

Creates a DIV tag

Creates an input (text) tag

Creates a span with the class of foo

$('<div>');

$('<input type="text" />');

$('<span>', { 'class': 'foo'});

DOM Creation

Thursday, July 5, 12

Replaces the content of #foo with:Testing

Replaces the content of #bar with:<strong>Testing</strong>

$('#foo') .html("<strong>Testing</strong>"); $('#bar') .text("<strong>Testing</strong>");

DOM Override

Thursday, July 5, 12

Insertion (inside):-append-appendTo-html-prepend-prependTo-textInsertion (outside):-after-before-insertAfter-insertBefore

$('<div>') .appendTo($('#foo'));

$('#foo') .append($('<span>'));

$('<div>') .prependTo($('#bar')); $('#baz') .after($('<span>'));

$('<div>') .insertBefore($('#baz'));

DOM Insertion

Thursday, July 5, 12

AJAX

•Asynchronous JavaScript And XML

•Though never use XML, use JSON

• jQuery has an AJAX library

•Wraps all the different browser quirks

• IE is weird

Thursday, July 5, 12

$.ajax({ url: "test.php", success: function(data){ $('div.status').addClass("done") .html(data); }});

AJAX

Thursday, July 5, 12

Cross-Domain

•Browser will not fire AJAX requests to a domain outside the one said JavaScript was loaded from

• If you include http://sub.domain.tld/file.js, it cannot make AJAX requests to http://another.tld/

• It can make requests to http://domain.tld/

Thursday, July 5, 12

JSONp

•Workaround to cross-domain

•Load like it is a javascript file (create an inject a script tag into the DOM)

•Response is a function (defined by a callback GET parameter) that executes and returns value

Thursday, July 5, 12

["api", "response"] callback(["api", "response"]);

JSONpdomain.tld/api.json domain.tld/api.jsonp?callback=callback

Thursday, July 5, 12

$.ajax({ dataType: 'jsonp' , url: 'http://search.twitter.com/search.json' , data: { q: "#tek12" } , success: function(resp) { jQuery.each(resp.results, function(id, tweet){ $('<div>', { 'class': 'tweet' }) .append($('<strong>', { 'class': 'user' , text: '@' + tweet.from_user })) .append($('<span>',{ 'class': 'text' , text: tweet.text })) .appendTo($('#tweets')); }); }});

JSONp

Thursday, July 5, 12

Create new :inline filter (checks if display is set to inline)

Works like any other native inline

$.expr[':'].inline = function(elem){ var $elem = $(elem) , disp = $elem.css('display'); return disp === 'inline';};

$('div a:inline') .css('color', 'red');

$('span:not(:inline)') .css('color', 'blue')

Extending: Custom Filters

Thursday, July 5, 12

(function($, global, undefined){

var defaults = { foo: "bar" };

var methods = { init: function(options) { // Merge user defined options options = $.extend(true, {}, defaults, options); return this; }, method: function() { }, }

$.fn.foo = function(method) { if( methods[method] ) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method == 'object' || !method) { return methods.init.apply(this, arguments); } else { $.error('Method ' + method + ' does not exist'); return undefined; } }

})(jQuery, window);

Thursday, July 5, 12

Resources

http://api.jquery.com/

Thursday, July 5, 12

Underscore.js

Thursday, July 5, 12

Underscore.js

DocumentCloud

2009

Thursday, July 5, 12

Underscore.js

•Functional, self-contained micro library

•Uses chaining for expressiveness

•Does not inject methods into native objects!

Thursday, July 5, 12

Functional Programming

•Functions are mappings between input and output

•No side-effects

• Input A always results in output B

•No OOP

•LISP, Haskell, Erlang

Thursday, July 5, 12

Underscore.js

•_(coll).method(arg1, ..)

•_.method(coll, arg1, ..)

Thursday, July 5, 12

Underscore.jsCollections

•each•map•reduce•reduceRight•find•filter•reject•all•any•include•invoke•pluck•max•min•sortBy•groupBy•sortedIndex•shuffle•toArray•size

Arrays•first•initial•last•rest•compact•flatten•without

•union•intersection•difference•uniq•zip•indexOf•lastIndexOf•range

Functions•bind•bindAll•memoize•delay•defer•throttle•debounce•once•after•wrap•compose

Objects•keys•values•functions•extend•pick•defaults•clone•tap

•has•isEqual•isEmpty•isElement•isArray•isObject•isArguments•isFunction•isString•isNumber•isFinite•isBoolean•isDate•isRegExp•isNaN•isNull•isUndefined

Utility•noConflict•identity•times•mixin•uniqueId•escape•result•template

Chaining•chain•value

Thursday, July 5, 12

Maps function to each element in the input collection

var inp = [1, 2, 3] , out = _.map(inp, function(n){ return n*2; });

//out = [2, 4, 6]

Map

Thursday, July 5, 12

Reduces collection to a single value. mem is the initial state, each successive iteration must be returned

var inp = [1, 2, 3];

_(inp).reduce(function(mem, n){ return mem + n;});

//Iter 0: mem = 1 | n = 2//Iter 1: mem = 3 | n = 3//Returns: 6

Reduce

Thursday, July 5, 12

Iterates over a collection and extracts the values for the input key (assumes all elements in the collection are objects/arrays)

var stooges = [ {name: 'moe', age: 40} , {name: 'larry', age: 50} , {name: 'curly', age: 60}];

_.pluck(stooges, 'name');

//Returns ["moe", "larry", "curly"]

Pluck

Thursday, July 5, 12

Returns the max item in a collection.

If second argument (iterator) provided, will use to produce the value to be compared

var stooges = [ {name: 'moe', age: 40} , {name: 'larry', age: 50} , {name: 'curly', age: 60}];

_.max(stooges, function(s){ return s.age; });

//Returns {name: 'curly', age: 60}

Max (Min)

Thursday, July 5, 12

Returns the keys from a dictionary as an array

_.keys({ one: 1, two: 2, three: 3});

//Returns ["one", "two", "three"]

Keys

Thursday, July 5, 12

Maps a duplicate input dictionary on top of a predefined “default” dictionary

var iceCream = { flavor: "chocolate"};

_.defaults(iceCream, { flavor: "vanilla" , sprinkles: "lots"});

//Returns {flavor : "chocolate", sprinkles : "lots"}

Defaults

Thursday, July 5, 12

When chain is initiated, method return a self-reference back to underscore but with the value attached [similar to opening with _(val)].

The chain continues until the value is extracted using .value()

var stooges = [ {name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];

var youngest = _.chain(stooges) .sortBy(function(s){ return s.age; }) .map(function(s){ return s.name + ' is ' + s.age; }) .first() .value();

//Returns "moe is 21"

Chaining

Thursday, July 5, 12

chain: begins a chain

map: takes dictionary and maps to a nested array [[key, val],[key, val], ..]

sortBy: sorts array returned by map by key (first element)

reduce: reforms an object using the nested list, [0] as key and [1] as value

value: spits out the value an ends the chain

_(request.params).chain() .map(function(v, k) { return [k,v]; }) .sortBy(function(a) { return a[0]; }) .reduce(function(s, v){ s[v[0]] = v[1]; return s; }, {}) .value();

Chain: FUN!

Thursday, July 5, 12

Backbone.js

Thursday, July 5, 12

Backbone.js

DocumentCloud

2010

Thursday, July 5, 12

Backbone.js

•Micro application framework

•Relies on jQuery/Zepto and Underscore.js

•Provides Views, Models, Collections, and Router

• If standard REST, default sync will work out of box

Thursday, July 5, 12

Model

•Fires events on value changes

•Must use model.get() and model.set()

Thursday, July 5, 12

Collection

•Collection of models

•Can be enforced

•Fires events on add, remove, reset, etc

Thursday, July 5, 12

View

•Creates own DOM object (or utilizes existing one)

•Easy event delegation/undelegation

Thursday, July 5, 12

Router

•Hash/History Router

•History management abstraction provided

Thursday, July 5, 12

Require.js

Thursday, July 5, 12

Require.js

James Burke

2009

Thursday, July 5, 12

Require.js

• Implements AMD

•Asynchronous Module Definition

•Dependency Management

Thursday, July 5, 12

r.js

•Optimizer, Compiler

•Concatenates dependencies into single file, optionally runs closure/uglifyjs/etc

Thursday, July 5, 12

Other Libraries Of Note

Thursday, July 5, 12

Compilers/Compressors

•UglifyJS• http://marijnhaverbeke.nl/uglifyjs

• JSmin:• http://www.crockford.com/javascript/jsmin.html

•YUI Compressor• http://developer.yahoo.com/yui/compressor/

http://marijnhaverbeke.nl/uglifyjs

Thursday, July 5, 12

Lawnchair

•HTML5 localstorage abstraction

•Good suite of storage adapaters

•DOM, webkit-sqlite, etc

http://brian.io/lawnchair

Thursday, July 5, 12

Moment.js

•Date/Time library

•Finally! Almost as easy as \DateTime and strtotime()

http://momentjs.com/

Thursday, July 5, 12

Enyo

•Application Framework

•Developed for the HP/Palm TouchPad

•Now open-source

•Designed for nested views and complex, finger-based UI

http://enyojs.com/

Thursday, July 5, 12

And Many More!

http://microjs.com/

Thursday, July 5, 12

https://joind.in/6503

http://bit.ly/js-ruby-wat

Thursday, July 5, 12

Recommended