7. Data Types
• number
• string
• boolean
• object
• null
• NaN
• undefined
Thursday, July 5, 12
8. Strings
• Are Objects, have methods
Thursday, July 5, 12
9. Strings
"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
Thursday, July 5, 12
10. String to Number
parseInt("56"); //56
parseInt("42.567"); //42
parseInt("asdf"); //NaN
parseInt("5a6"); //5
parseFloat("24.68"); //24.68
parseFloat("asdf"); //NaN
parseFloat("24a"); //24
Thursday, July 5, 12
11. 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
13. in or hasOwnProperty()
• Tough call:
• .hasOwnProperty() more consistent
• in checks inherited properties
• Used in for loop
Thursday, July 5, 12
14. in
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
Thursday, July 5, 12
15. Arrays
• Special object
• Numerical keys only
• Keeps intrinsic ordering
• Short ([]) and Long (new Array()) syntax
Thursday, July 5, 12
16. Arrays
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"]
Thursday, July 5, 12
18. Arrays
var arr1 = [1,2,3];
var arr2 = [3,4,5];
arr1.concat(arr2); //[1,2,3,3,4,5]
Thursday, July 5, 12
19. delete
• Removes element from an object
• “Removes element from an array”
• Not really, just sets it to undefined
Thursday, July 5, 12
20. 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
21. Functions
function Foo() {
//...
}
Foo(); //valid
Bar(); //valid
function Bar() {
//...
}
Thursday, July 5, 12
22. Functions
function Foo() {
}
Foo.bar = "value";
'bar' in Foo; //true
Foo.bar == "value"; //true
Thursday, July 5, 12
23. 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
24. arguments
• A special variable found inside a function
• A not-quite array object containing all the
function arguments
Thursday, July 5, 12
25. arguments
function sum() {
var x = 0;
for (var i = 0; i < arguments.length; ++i) {
x += arguments[i];
}
return x;
}
sum(1, 2, 3); //6
Thursday, July 5, 12
26. typeof
• Determines a variables type
• Returns a string
Thursday, July 5, 12
28. 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
29. 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 DOM
Thursday, July 5, 12
31. 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
32. Closures
function Foo() {
var count = 0;
return function() {
count = count + 1;
return count;
};
}
var bar = Foo();
bar(); //1
bar(); //2
bar(); //3
Thursday, July 5, 12
33. Closures
function createAdder(amount) {
return function(input) {
return input + amount;
};
}
var add2 = createAdder(2);
add2(2); //4
add2(8); //10
var add3 = createAdder(3);
add3(3); //6
add3(7); //10
Thursday, July 5, 12
34. Module Pattern
(function(exports, undefined){
//ALL your code here
var localVar = "bar"
globalVar = "baz";
exports.foo = "bat";
})(window);
alert(localVar); //error
alert(globalVar); //"baz"
alert(window.globalVar); //"baz"
alert(foo); //"bat"
alert(window.foo); //"bat"
BEWARE: export (singular) is a reserved word in Safari
Thursday, July 5, 12
36. 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
37. Global & Local
var outerScope = 10;
var outerScope2 = 10;
function Foo() {
var outerScope = 20;
var innerScope = 20;
globalVariable = 30;
outerScope2 = 40;
}
Foo();
alert(outerScope); //10
alert(outerScope2); //40
alert(innerScope); //error
alert(globalVariable); //30
Thursday, July 5, 12
38. Lexical Scoping
function Foo() { function Foo() {
var baz = 1; var baz = 1;
return Bar();
function Bar() { }
return baz;
} function Bar() {
return baz;
return Bar(); }
}
Foo(); //baz is not defined
Foo(); //1
Thursday, July 5, 12
39. Hoisting
foo(); //called foo! Named functions are parsed and
made available before general
function foo() {
evaluation (thus “hoisted” to the top
console.log('called foo!');
}
of the file).
foo(); //called foo! Anonymous functions, or functions
assigned to variables, require
evaluation before they become
bar(); //undefined is not a function
available
var bar = function() {
console.log('called bar!');
}
bar(); //called bar!
Thursday, July 5, 12
40. Practical: Currying
function makeAdder(a) {
return function(b) {
return a+b;
}
}
var two = makeAdder(2);
two(1); //3
two(2); //4
two(3); //5
Thursday, July 5, 12
42. 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
43. this
var Foo = {
bar: "bar",
baz: function() {
return this.bar;
}
};
Foo.baz(); //"bar"
Foo.bar = "bat";
Foo.baz(); //"bat"
var baz = Foo.baz;
baz(); //undefined
Thursday, July 5, 12
44. this
var Foo = {
bar: "bar",
baz: function() {
return this.bar;
}
};
Foo.bat = function() {
return this.bar + "bat";
};
Foo.bat(); //"barbat"
Thursday, July 5, 12
45. call & apply
• Methods in the function prototype
• Change the context in which a function
executes!
Thursday, July 5, 12
46. call & apply
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"
Thursday, July 5, 12
47. Practical: Binding
function bind(func, context) {
return function() {
return func.call(context, arguments);
}
}
Thursday, July 5, 12
53. 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
54. OOP... Kinda...
Foo
function Foo() {
//The "Constructor"
} ‣ bar
‣ prototype
Foo.bar = function() { ‣ baz
//A "Static" Function ‣ constructor
}
‣ __proto__
Foo.prototype.baz = function() {
//A "Method"
};
Thursday, July 5, 12
55. new
instance
var instance = new Foo();
instance.baz(); //works ‣ __proto__
instance.bar(); //error ‣ baz
‣ constructor
Foo.bar(); //works ‣ __proto__
Foo.baz(); //error
‣ ...
Foo.prototype.baz(); //works
Thursday, July 5, 12
59. Asynchronous
• setTimeout, setInterval allow you to have
code executing asynchronously while other
code executes
Thursday, July 5, 12
60. setInterval
var id = setInterval(function() {
//Code to execute every 1000 milliseconds
}, 1000);
//clearInterval(id); to stop
Thursday, July 5, 12
61. setTimeout
var id = setTimeout(function() {
//Code to execute after 1000 milliseconds have passed
}, 1000);
//clearTimeout(id); to cancel
Thursday, July 5, 12
63. Nifty Trick
setTimeout(function() {
//Code to run in parallel
//while the code after is
//executed.
}, 1);
//Code here will execute immediately
//without waiting on the above
Thursday, July 5, 12
70. Async Script Loading
var script = Creates a script element, set its src
document.createElement('script'); and async properties
script.src =
"http://path.to/script.js";
script.async = true;
Insert the script before the first
script tag in the body of the
var s = document document
.getElementsByTagName('script')[0];
s.parentNode
.insertBefore(script, s);
Thursday, July 5, 12
71. DOM
https://developer.mozilla.org/en/Gecko_DOM_Reference
Thursday, July 5, 12
75. 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
76. 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
77. 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
78. 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
79. Script
• Provides a familiar break-point debugging
workflow
Thursday, July 5, 12
81. Coding Styles
• Mostly your standard C based style
techniques
• Special considerations
• Semi-colons? No semi-colons?
• Leading , ?
• Prototype Definition?
Thursday, July 5, 12
82. Comma Style
var dict = { var dict = {
foo: 'bar', foo: 'bar'
baz: 'bat' , baz: 'bat'
}; };
Thursday, July 5, 12
83. var Declaration Style
var foo; var foo
var bar; , bar
var baz; , baz;
Thursday, July 5, 12
84. Prototype Style
function Foo() { function Foo() {
} }
Foo.prototype.bar = function(){ Foo.prototype = {
bar: function() {
};
}
}
Thursday, July 5, 12
85. 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
87. Safe Extension
App = window.App || {}; Grab global App dictionary, or
create if not found
App.utility = function() {
//Globally available, no
//conflicts Add a function utility, is now
}; globally accessible without fearing
collision with other functioned
similarly named
Thursday, July 5, 12
88. IIFE
(function(exports){ Immediately
exports.foo = function() { Invoked
Function
};
Expression
var bar = function() {
Function is defined then
}; immediately invoked. Closest thing
})(window); to a namespace/module system.
foo(); //success
bar(); //not found!
Prevents variable leakage into outer
scopes
Thursday, July 5, 12
89. Pro-Tip
• Create an application namespace as a
dictionary in the global scope
• Add in any global level configuration values
Thursday, July 5, 12
91. 2001 JSON
Douglas Crockford
Awesome
Thursday, July 5, 12
92. 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
96. January 2006 jQuery
John Resig
Author, jQuery
Thursday, July 5, 12
97. 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
98. Selectors
• Superset of CSS3 selectors
• Custom Pseudo-Classes
• Filters in jQuery parlance
Thursday, July 5, 12
99. Selectors
• $('selector') returns jQuery object for
chaining purposes
• Chained methods will apply to all results if
selector matches multiple elements
Thursday, July 5, 12
100. Selectors
$("p:not(.special)") Finds all p tags that do not have the
.addClass("semi-special");
class special, and adds the class
semi-special
Thursday, July 5, 12
101. Selectors
$('select option:selected').val(); Gets the value of the selected option
in a select box
Thursday, July 5, 12
102. Testing Elements
$('.foo').is(':visible'); Tests matched element against
selector, in this case the jQuery
‘visible’ selector
Thursday, July 5, 12
103. Custom Filters
• jQuery provides the ability to create custom
filters
• :radio, :hidden, etc are custom filters
provided by default
Thursday, July 5, 12
105. Chaining
• Most all jQuery methods are chain-able
• If $() returns > 1 element, methods invoked
will apply to all matched
Thursday, July 5, 12
106. Chaining
$('ul.first') Find all ul with class first
.find('.foo')
.css('color', 'red')
.end().find('.bar') Find elements of class foo that are
.css('color', 'blue') children of the top level matched set
.end();
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;
Thursday, July 5, 12
107. Events
• jQuery wraps an event handling system
• Handles browser events, AJAX events, and
custom events
Thursday, July 5, 12
108. Events
$(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
});
Thursday, July 5, 12
109. Events
$('img').hover(function(){
//Do something when user hovers over
//any img tag
});
Thursday, July 5, 12
110. Events
• Event functions have the matched element
from jQuery bound as this
Thursday, July 5, 12
111. jQuery
$('a.foo').click(function(){ Listen for click on a.foo
var $this = $(this)
, href = $this.href();
this will be the specific a.foo
//href will be the clicked element that was clicked
//links href
});
Thursday, July 5, 12
112. 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
113. Live Events
$('.grandparent') All a tags that exist at some point
.on('click', 'a', function(e){
as a descendant of .grandparent
var $target = $(e.target);
will trigger this event on click
//$target will *usually*
//be the a tag, though Any future a tags that are added as
//sometimes it will be a a descendant of .grandparent
//nested tag
});
will trigger this event on click
Thursday, July 5, 12
114. Proxy
function Foo() {} Create a Prototype object for
example purposes, then create new
Foo.prototype.baz = function() {};
instance.
Foo.prototype.bar = function() {
this.baz();
}; The first click handler will fail. The
keyword this will not be a
var instance = new Foo(); reference to the instance of Foo as
expected, but a reference to the
$('element').click(instance.bar);
matched DOM element that was
$('element').click( clicked.
jQuery.proxy(
instance.bar, jQuery.proxy() will wrap your
instance function such that further
);
invocations will use the context you
);
set for this
Thursday, July 5, 12
115. Animation
$('.button').click(function(){ When .button is clicked, fade out
$('img.preview') img.preview over 600 milliseconds
.fadeOut(600, function() {
and then remove it from the DOM
$(this).remove();
});
});
Thursday, July 5, 12
116. animate
$('#book').animate({ Animate the following attributes
opacity: 0.25, over the course of 5 seconds:
left: '+=50',
opacity to 25%
height: 'toggle'
},
move to the right 50px
5000, toggle height
function() {
// Animation complete.
}
);
Thursday, July 5, 12
117. 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
118. DOM Creation
$('<div>'); Creates a DIV tag
$('<input type="text" />');
Creates an input (text) tag
$('<span>', {
'class': 'foo' Creates a span with the class of foo
});
Thursday, July 5, 12
119. DOM Override
$('#foo') Replaces the content of #foo with:
.html("<strong>Testing</strong>"); Testing
$('#bar')
.text("<strong>Testing</strong>");
Replaces the content of #bar with:
<strong>Testing</strong>
Thursday, July 5, 12
121. 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
123. 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
124. 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
127. Extending: Custom Filters
$.expr[':'].inline = function(elem){ Create new :inline filter (checks
var $elem = $(elem)
if display is set to inline)
, disp = $elem.css('display');
return disp === 'inline'; Works like any other native inline
};
$('div a:inline')
.css('color', 'red');
$('span:not(:inline)')
.css('color', 'blue')
Thursday, July 5, 12
131. 2009 Underscore.js
DocumentCloud
Thursday, July 5, 12
132. Underscore.js
• Functional, self-contained micro library
• Uses chaining for expressiveness
• Does not inject methods into native objects!
Thursday, July 5, 12
133. 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
136. Map
var inp = [1, 2, 3] Maps function to each element in
, out = _.map(inp, function(n){ the input collection
return n*2;
});
//out = [2, 4, 6]
Thursday, July 5, 12
137. Reduce
var inp = [1, 2, 3]; Reduces collection to a single
value. mem is the initial state, each
_(inp).reduce(function(mem, n){
return mem + n;
successive iteration must be
}); returned
//Iter 0: mem = 1 | n = 2
//Iter 1: mem = 3 | n = 3
//Returns: 6
Thursday, July 5, 12
138. Pluck
var stooges = [ Iterates over a collection and
{name: 'moe', age: 40} extracts the values for the input key
, {name: 'larry', age: 50}
(assumes all elements in the
, {name: 'curly', age: 60}
];
collection are objects/arrays)
_.pluck(stooges, 'name');
//Returns ["moe", "larry", "curly"]
Thursday, July 5, 12
139. Max (Min)
var stooges = [ Returns the max item in a
{name: 'moe', age: 40} collection.
, {name: 'larry', age: 50}
, {name: 'curly', age: 60}
];
If second argument (iterator)
provided, will use to produce the
_.max(stooges, function(s){ value to be compared
return s.age;
});
//Returns {name: 'curly', age: 60}
Thursday, July 5, 12
140. Keys
_.keys({ Returns the keys from a dictionary
one: 1, as an array
two: 2,
three: 3
});
//Returns ["one", "two", "three"]
Thursday, July 5, 12
141. Defaults
var iceCream = { Maps a duplicate input dictionary
flavor: "chocolate" on top of a predefined “default”
};
dictionary
_.defaults(iceCream, {
flavor: "vanilla"
, sprinkles: "lots"
});
//Returns {flavor : "chocolate",
sprinkles : "lots"}
Thursday, July 5, 12
142. Chaining
var stooges = [ When chain is initiated, method
{name : 'curly', age : 25}, return a self-reference back to
{name : 'moe', age : 21},
underscore but with the value
{name : 'larry', age : 23}
];
attached [similar to opening with
_(val)].
var youngest = _.chain(stooges)
.sortBy(function(s){ The chain continues until the value
return s.age;
is extracted using .value()
})
.map(function(s){
return s.name + ' is ' + s.age;
})
.first()
.value();
//Returns "moe is 21"
Thursday, July 5, 12
143. Chain: FUN!
_(request.params).chain() chain: begins a chain
.map(function(v, k) {
return [k,v];
map: takes dictionary and maps to
})
.sortBy(function(a) { a nested array [[key, val],
return a[0]; [key, val], ..]
})
.reduce(function(s, v){ sortBy: sorts array returned by map
s[v[0]] = v[1]; return s;
by key (first element)
}, {})
.value();
reduce: reforms an object using the
nested list, [0] as key and [1] as
value
value: spits out the value an ends
the chain
Thursday, July 5, 12
145. 2010 Backbone.js
DocumentCloud
Thursday, July 5, 12
146. 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
147. Model
• Fires events on value changes
• Must use model.get() and model.set()
Thursday, July 5, 12
148. Collection
• Collection of models
• Can be enforced
• Fires events on add, remove, reset, etc
Thursday, July 5, 12
149. View
• Creates own DOM object (or utilizes existing
one)
• Easy event delegation/undelegation
Thursday, July 5, 12
150. Router
• Hash/History Router
• History management abstraction provided
Thursday, July 5, 12
157. Lawnchair
• HTML5 localstorage abstraction
• Good suite of storage adapaters
• DOM, webkit-sqlite, etc
http://brian.io/lawnchair
Thursday, July 5, 12
158. Moment.js
• Date/Time library
• Finally! Almost as easy as DateTime and
strtotime()
http://momentjs.com/
Thursday, July 5, 12
159. 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
160. And Many More!
http://microjs.com/
Thursday, July 5, 12