JavaScript Pattern
Agenda
About JavaScript Essential Practices Literals and Constructors Functions Object Creation Patterns Code Reuse Patterns
About Patterns
What’s Patterns? Not for copy-and-paste Useful abstraction Template or model for solving
Coding Patterns Design Patterns vs. Antipatterns
About JavaScript
Script language Interpreted language vs. Compiled language
Object-oriented Primitive types
number, string, boolean, null, undefined Native objects
Number, String, Boolean, Date, Array, Function… User-defined
About JavaScript
Prototype-based language No Classes
vs. Class-based language Prototype
Alteration prototypes during run-time
Dynamic typing Values have types but variables do not
About JavaScript
First-class functions Function literals or Function types Functions as first-class objects
Own properties and methods
ECMAScript 5 (be called ES5, for short) Vs. ECMAScript 3 (ES3) Strict mode Library extensions
Tools for JavaScript
Firebug If (console && console.firebug)If (console && console.firebug) Object inspection
console.dir(object)console.dir(object) Timing and profiling
console.time(message)console.time(message) Stack traces
console.trace()console.trace() Nested grouping
console.group(message)console.group(message)
Tools for JavaScript
Code Quality Tool JSLint
Strict mode-compliant Web Page Performance Diagnostics Tool
YSlow from Yahoo! Page Speed from Google
Books about web pages tuning High Performance Web Sites, O’Reilly Even Faster Web Site, O’Reilly
Essential Practices
Essential Practices
Maintainable code Readable Consistent Predictable Looks as be written by Same Person Documented
Essential Practices
Global variables Minimize Globals
Always use var to declare variables Single var Pattern
Other ways… Namespacing pattern Self-executing immediate function
Can Global Variables be delete? Hoisting problem
Essential Practices
For Loop Iterate over arrays or array-like objects
Cache the length of the array ++++ and ---- vs. i += 1i += 1 and i -= 1i -= 1 Use one less variable Count down to 0
For-in Loop Iterate over non-array objects
hasOwnProperty()hasOwnProperty() method
Essential Practices
Augmenting Built-in Prototypes Unpredictable code Except…
Future ECMAScript version or JavaScript implementation
Custom property or method does not exist
Switch Pattern Avoiding Implied Typecasting
==== and !=!= vs. ====== and !==!==
Essential Practices
Avoiding eval()eval() setInterval(), setTimeout()setInterval(), setTimeout() and new Function()new Function() eval()eval() Interfere with the scope chain Function()Function() is like a sandox JSON.parse()JSON.parse() method
Use parseInt() parseInt(string, radix)parseInt(string, radix) +”08”+”08” Number(“08”)Number(“08”)
Code Convention
Curly Braces {…}{…} Always use {…}{…} if only one statement in an ifif or a forfor Opening Brace Location
White space for (var i = 0; i < 10; i += 1) {…}for (var i = 0; i < 10; i += 1) {…} for (var i = 0, max = 10; i < max; i += 1) {…}for (var i = 0, max = 10; i < max; i += 1) {…} var a = [1, 2, 3]var a = [1, 2, 3] var o = {a: 1, b: 2}var o = {a: 1, b: 2} myFunc(a, b, c)myFunc(a, b, c) function myFunc( ) {…}function myFunc( ) {…} var myFunc = function () {…}var myFunc = function () {…}
Naming Convention
Camel case constructors functions methods variables: all lowercase words with underscore
Constants: use all capital letters Global variables: use all capital letters
Naming Convention
Private scope Underscore prefix(?)
e.g. _getName()_getName() properties methods
The Next…?
Write Comments Write to Be Read Write API Docs
Peer Reviews Tools for code better
Run JSLint Minification
Yahoo! YUI Compressor Google’s Closure Compiler
Literals and Constructors
Object Literals
var object = { };var object = { }; Change the values of properties and methods Delete / Add properties and methods
Blank object / Empty object inherited from Object.prototype
Object constructor Scope resolution
Look up the scope chain from the place you calling nenew Object()w Object()
Constructor
Add reusable methods to the prototype, but not the constructor function
Return this or any other object Invoke the constructor without newnew Return another object: that
Prototype is not available Self-Invoking constructor
Array Literal
var array = [ ];var array = [ ]; Array.isArrayArray.isArray method
Added from ES5 Array toString()
[object Array] Object toString()toString()
[object Object]
JSON
Syntax Similar to Object Literal Property names are wrapped in “…” No Functions Literal No Regular Expression Literal
JSON.parse()JSON.parse() / JSON.stringify()JSON.stringify() Browser build-in native methods jQuery.JSON YUI.JSON
Regular Expression Literal
var re = /pattern/gmi;var re = /pattern/gmi; var re = new RegExp(‘\pattern\’, ‘gmi’)var re = new RegExp(‘\pattern\’, ‘gmi’)
Global matching: g Multiline: m Case-insensitive matching: I Same regular expressions if their expressions are
equal each other
Primitive Wrappers
Built-in constructor Number()Number() String()String() Boolean()Boolean()
Useful methods work on primitives that is temporarily converted to an object
Primitives cannot be augmented with properties or methods
Error Objects
Error()Error(), SyntaxError()SyntaxError(), TypeError()TypeError() name, message
Throw…Catch Custom error object
Constructor Syntax
Functions
Function
2 very important features They are Objects They provide Local Scope
Can be… Created dynamically, Assigned to variables Augmented, Deleted in a few special cases Passed as arguments, Returned by other
functions Their own properties and methods
Function
Named Function Expression var var addadd = function = function addadd() {…}() {…};; Incompatible with IE
Unnamed Function Expression var var addadd = function () {…} = function () {…};; Function Expression Anonymous Function
Function
Function Declaration function function addadd() {…}() {…} Inside other functions or the global scope
Function’s name Pros
Debugging Recursive call
API Patterns
Help you provide better and cleaner interface to your functions Callback Pattern Configuration Objects Returning Functions Currying
Initialization Patterns
Help you perform initialization and setup tasks without polluting the global namespace Immediate Function Immediate Object Initialization Init-Time Branching
Performance Patterns
Help speed up the code Memoization Self-Defining Functions
Callback Patterns
Callback Function Template Method
Scope Pass the object that callback belonged to Pass the method (callback) as string
Asynchronous Event Listeners Cons
Out of order Timeout
setTimeout()setTimeout() setInterval()setInterval()
Function Patterns
Returning Function Return another function Use Closure to store private data
Self-Defining Function Create a new function assign to the same variable Initial work to be done only once Lazy function definition Original function will be lost when it redefined
Function Patterns
Immediate Function Self-Invoking, Self-Executing Execute a function as soon as it is defined
((function () {…}function () {…}());()); ((function () {…}function () {…})();)();
A scope sandbox for initialization code Pass arguments to immediate functions
Function Patterns
Immediate Function Return values
var result = var result = ((function () {return…}function () {return…}());()); var result = var result = ((function () {return…}function () {return…})();)(); var result = function () {return…}var result = function () {return…}();();
Bookmarklet Self-contained modules
Function Patterns
Immediate Object Initialization init() after object is created
(({…}{…})).init.init();(); (({…}.init{…}.init());());
DrawbackDrawback MinificationMinification No return values
Init-Time Branching Load-time branching e.g. Browser sniffing
Function Patterns
Memoization Pattern Use Properties to store Cached data
arguments.calleearguments.callee
Configuration Objects Substitute for a set of passed arguments
Curry Partial Application Currying
When to Use Currying?
Object Creation Patterns
Object Creation Patterns
Namespace pattern A generic namespacenamespace function All capital letters Drawbacks
A bit more to type Only global instance Long resolution lookup
Object Creation Patterns
Declaring Dependencies Declare the modules your code relies on at the
top of your function or module Realize the specific JS files are needed Easy to find and resolve dependencies Perform global symbol resolution only once
Private, Protected, or Public
Private Members Using Closure to access private members
Function Declaration as private functions
Privileged Methods Public methods have access to the private
members (properties or methods) A returned private variable can be modified if it’s
an object or array (Passed by Reference)
Private, Protected, or Public
Private members always are created when the constructor is invoked Add public reusable members to the prototype
property of the constructor Revelation pattern
Reveal private functions as public methods
Module Patterns
Provide structure and help organize your code as it grows
In common use all over our web applications Combine the following patterns
Namespaces Immediate Functions Private and Privileged members Declaring dependences
Module Patterns
Reveal Module Pattern Return the object has triggers of private functions
Modules that Create Constructors Return the constructor function
Importing Globals into a Module
Sandbox Pattern
Drawbacks of Module pattern No way to have 2 versions of the same
application or library Long, dotted names to type and resolve at
runtime A Global Constructor Adding Modules
Static Members
No instance-specific Public Static member
Be accessible outside via Constructor
Private Static member Not accessible outside Using Closure feature
Object Constants
All capital letters Math.PIMath.PI Number.MAX_VALUENumber.MAX_VALUE
General-Purpose Constants object set(name, value)set(name, value) isDefined(name)isDefined(name) get(name)get(name)
Chaining Pattern
Call methods on an object after the other Pros
Save some typing Create more concise code
Cons Debug code more difficult
Always return thisthis if your method has no return value
method() Method
Help you define the whole “class” with a single statement
Drawback Debug code more difficult Add methods to thisthis is inefficient
Methods are re-created with every instance Consume more memory
Reusable methods should be added to the prototypeprototype property of the constructor
Code Reuse Patterns
To Reuse Code…
Inheritance That is one way for us to reuse code, but not the
only way Composition / Delegation
Prefer object composition to class inheritance Prototype Inheritance
Prototype Constructor
The Default Pattern (#1) Child.prototype = new Parent( );Child.prototype = new Parent( );
The Default Pattern (#1)
Benefits Inherit parent properties and parent prototype
members Drawbacks
Inherit parent properties added to thisthis and the child prototype properties
Can’t pass parameters to the child constructor General rule of thumb with constructors
Reusable members should be added to the prototype
Rent-a-Constructor (#2) function Child (…) {function Child (…) {
Parent.apply(this, arguments); Parent.apply(this, arguments);}}
Rent-a-Constructor (#2)
Benefits Borrowing Constructor Pattern Only inherit parent properties added to thisthis
inside the parent constructor Drawbacks
Can’t inherit parent prototype members Multiple Inheritance by Borrowing
Constructors
Rent and Set Prototype (#3) function Child (…) {function Child (…) {
Parent.apply(this, arguments); Parent.apply(this, arguments);}}Child.prototype = new Parent( );Child.prototype = new Parent( );
Rent and Set Prototype (#3)
Benefits Combine #1 and #2 patterns
Drawbacks Parent constructor is called twice Parent members get inherited twice
Share the Prototype (#4) Child.prototype = Parent.protoype;Child.prototype = Parent.protoype;
Share the Prototype (#4)
Benefits Child prototype is equals to parent prototype All objects share the same prototype
Drawbacks One child modified the prototype that affects all
parents
A Temporary Constructor (#5) var F = function( ) { };var F = function( ) { };
F.prototype = Parent.prototype;F.prototype = Parent.prototype;Child.prototype = new F( );Child.prototype = new F( );Child.uber = Parent.prototype;Child.uber = Parent.prototype;Child.prototype.constructor = Child;Child.prototype.constructor = Child;
A Temporary Constructor (#5)
Benefits A proxy function between child and parent Parent constructor members adds to thisthis are n
ot inherited Holy Grail version
Storing super (uberuber) class Resetting constructor pointer Use an immediate function to store proxy functi
on in it’s closure
Klass
Emulating Class A generic klassklass function
Implementation Create a Child( )Child( ) constructor function Inherit parent via Holy Grail pattern Add parent members to child prototype
Prototypal Inheritance function object (o) {function object (o) {
function F( ) { } function F( ) { } F.prototype = o; F.prototype = o; return new F( ); return new F( );}}
Prototypal Inheritance
Feature Modern Classless Pattern A generic objectobject function Create a child object gets its functionality from
parent object Addition to ES5
var child = Object.create(parent);var child = Object.create(parent);
Inherit by Copying Properties
Feature A generic extendextend function Create a child object gets its functionality from
parent object by copying A deep copy version
extendDeepextendDeep
Mix-ins
Feature A generic mixmix function Create a child object gets its functionality from an
y number of parent objects by copying Multiple Inheritance Implementation
Borrowing Methods
Feature A generic bindbind function Use some methods without inheriting other metho
ds A common use for this pattern
Array.slice.call(arguments)Array.slice.call(arguments) Array( ).slice.call(argument)Array( ).slice.call(argument)
Addition to ES5 Function.prototype.bind( )Function.prototype.bind( )
Design Patterns
Singleton
Purpose Creating only one object of a “class”
New instance via Object Literal New instance via Constructor
Store in a Global Variable Cache in a Static Property of the constructor Wrap in a Closure
Private Static Member pattern Self-Defining Functions
Factory
Purpose A method that creates objects of type specified as
a string at runtime Map object types to the constructors that
create different objects Built-in Object Factory
new Object(?)new Object(?)
Iterator
Purpose Providing an API to loop over and navigate
around a complex custom data structure Additional convenience methods
rewind( )rewind( ) current( )current( )
Decorator
Purpose Tweaking objects at runtime by adding functionalit
y from predefined decorator objects Undercorating / Undoing a decoration
Implementation Using a Array It’s no need to use Inheritance
Decorator Implementation
Strategy
Purpose Keeping the same interface while selecting the be
st strategy to handle the specific task (context) The validatorvalidator is generic and could be kept lik
e this for all validation use cases
Facade
Purpose Providing a more convenient API by wrapping co
mmon methods into a new one Handle browser events
stopPropagation( )stopPropagation( ) preventDefault( )preventDefault( )
Proxy
Purpose Wrapping an object to control the access to it,
with the goal of avoiding expensive operations Proxy serves as a guardian of the “real
subject” and tries to have the real subject do as little work as possible
Proxy As a Cache More less Network Round-trips Memorization Pattern
Proxy As a Cache
Mediator
Purpose Promoting loose coupling and then helping
improve maintainability Independent colleagues don’t communicate
directly, but through a mediator who notifies the change to any other colleagues
Mediator in Keypress Game
Observer
Purpose Loose coupling by creating “observable” objects
that notify all their observers when an interesting event occurs
Subscriber (Observer) / Publisher (Subject) Publisher has important methods
subscribe( )subscribe( ) unsubscribe( )unsubscribe( ) publish( )publish( )
DOM and Browser Patterns
Separation of Concerns
3 main concerns in web application Content - HTML Presentation - CSS Behavior - JavaScript
In Practice… Page is still readable if CSS is off Page perform main purpose if JavaScript is off Not using inline event handlers or stylestyle attributes Using meaningful HTML elements
DOM Access
Bottleneck DOM is separated from JavaScript engine
Good Parts… Avoiding DOM access in loop Assigning DOM reference to local variables Using selectors API
document.document.querySelector(querySelector(“#widget”“#widget”));; document.document.querySelectorAll(querySelectorAll(“.widget”“.widget”));;
Cache the length of HTML collections document.document.getElementByIdgetElementById(“id”)(“id”) is fastest way
DOM Manipulation
Bottleneck Modify DOM to repaint the browser’s screen and r
ecalculate element’s geometry Batch the changes and performing them outsi
de of the livelive document tree Use a document fragment to contain new nodes
var frag = document.var frag = document.createDocumentFragment()createDocumentFragment();; Make all change to the Clone of root of subtree
var newnode = oldnode.var newnode = oldnode.cloneNode(cloneNode(truetrue));; oldnode.oldnode.parentNode.replaceChildparentNode.replaceChild(newnode, oldnode);(newnode, oldnode);
Events
Bottleneck Event handling in IE (version < 9) and W3C-confo
rming implementations is different Access event
Passed to Callback event handler Use onclickonclick property through window.eventwindow.event
e = e || e = e || window.eventwindow.event;;
Access target of event src = e.src = e.targettarget || e. || e.srcElementsrcElement;;
Event Handling
W3C-conforming Event Capturing Cancel Event Propagatio
n e.e.stopPropagationstopPropagation();();
Prevent default action e.e.preventDefaultpreventDefault();();
IE (version < 9) Event Bubbling Cancel Event Propagati
on cancelBubblecancelBubble = = truetrue;;
Prevent default action returnValuereturnValue = = falsefalse;;
Event Delegation Pattern
Benefits Suitable for Event Bubbling Reduce the number of event listeners attached
to separate nodes Better performance and cleaner codes
Drawbacks Filter out the uninteresting events
Use 3rd JavaScript library
Event Handling 3rd-party API
jQuery version 1.0 ~ 1.3
$(target).$(target).bindbind(event, callback);(event, callback); $(target).$(target).triggertrigger(event);(event); $(target).$(target).oneone(event, callback);(event, callback); $(target).$(target).livelive(event, callback);(event, callback);
version 1.4.2 ~ $(container).$(container).delegatedelegate(target, event, callback);(target, event, callback);
Yahoo! YUI Y.Y.delegatedelegate(event, callback, (event, callback, containercontainer, target);, target);
Long-Running Scripts
Issue Browser complains a Long-Running Script and as
k user if it should be stopped Solutions
setTimeout()setTimeout() Use 1ms timeout chunks cause task to complete slowl
y overall, but browser UI will remain responsive WebWorkersWebWorkers
Web workers provide background thread support in the browser
Remote Script
AJAX (Asynchronous JavaScript and XML) XMLHttpRequest Restricted same-domain
JSONP (JSON with Padding) HTML Script element Injection
script.src = url;script.src = url; Execute a client-side callback with server-side JS
ON data passed from different domain Unrestricted cross-domain
Remote Script
Frame HTML iFrame element Injection
iframe.src = url;iframe.src = url; Image Beacons pattern
Send data to server but not expecting a response new Image()new Image().src = “http://...”;.src = “http://...”; Response with 1x1 GIF image or “204 No Content204 No Content”
HTML5 Cross-document messaging
otherWindow.otherWindow.postMessagepostMessage(string, targetOrigin);(string, targetOrigin);
Deploying JavaScript
Combining Scripts Benefits
Speed up Page Loading Drawbacks
More preparations before deploying into production Help from Ant tool
Lose some of the caching benefits Spilt up to 2 bundles: barely change and hardly change
Come up with some naming and versioning pattern for bundle
Deploying JavaScript
Minifying Yahoo! YUI Compressor Google’s Closure Compiler
Compressing Enable GZIP compression in server-side
Expires Header Stay files in browser cache as far as possible Rename files if they have been changed
Construct or Using CDN Google, Microsoft, Yahoo! hosts popular libraries
Using Popular CDN
Benefits Decreased Latency
Clients will automatically target the closest available server in the network
Increased Parallelism Eliminate one request to your site, allowing more of
your local connect to download in parallel Better Caching
Clients will only need download it once if it had been visited on another website using the same CDN
Loading Strategies
Minimize blocking effect Place <script> at the closing </body> element
HTTP Chunking Non-blocking downloads *.js
Load script with an AJAX and eval()eval() it as a string Using deferdefer / asyncasync attributes of <script> Using Dynamic <script> Pattern
Append this dynamic <script> to <head> or <body> Also insert this dynamic <script> before the first availa
ble <script>
Dynamic <script> Pattern
Drawbacks Any other <script> can’t rely on the main *.js bein
g load on the page Solution
Using anonymous function to wrap separate inline scripts into a function and add each function into an empty array
Loop through this array in main script and execute all of them
Better Dynamic <script> Pattern
Lazy Loading Load external *.js unconditionally after page load
event Loading on Demand
Load only the parts *.js that are really needed Create a method that loads <script> dynamically
and execute a callback when <script> is loaded In W3C-conforming, subscribe loadload event In IE (version < 9), subscribe readystatechangereadystatechange event
and look for a readystatereadystate === “loadload” or “completecomplete”
Better Dynamic <script> Pattern
Preloading JavaScript Load external *.js are not needed on current page
but on following pages without parsing and executing *.js immediately
This works not only for *.js, but also *.css and images, e.g. *.jpg, *.png etc.
Drawbacks The presence of user agent sniffing Some browsers probably have a separate cache for i
mages, so preloading *.js or *.css will not be used
Better Dynamic <script> Pattern
Preloading JavaScript Create a method using init-time branching pattern
to handle browser sniffing Using invisible <object> in W3C-conforming Using new Image()new Image().src.src in IE
Conclusion
Q&A