Java Script Patterns

103
JavaScript Pattern [email protected]

description

Refer to an IT book "O'Relly JavaScript Patterns".

Transcript of Java Script Patterns

Page 1: Java Script Patterns

JavaScript Pattern

[email protected]

Page 2: Java Script Patterns

Agenda

About JavaScript Essential Practices Literals and Constructors Functions Object Creation Patterns Code Reuse Patterns

Page 3: Java Script Patterns

About Patterns

What’s Patterns? Not for copy-and-paste Useful abstraction Template or model for solving

Coding Patterns Design Patterns vs. Antipatterns

Page 4: Java Script Patterns

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

Page 5: Java Script Patterns

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

Page 6: Java Script Patterns

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

Page 7: Java Script Patterns

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)

Page 8: Java Script Patterns

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

Page 9: Java Script Patterns

Essential Practices

Page 10: Java Script Patterns

Essential Practices

Maintainable code Readable Consistent Predictable Looks as be written by Same Person Documented

Page 11: Java Script Patterns

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

Page 12: Java Script Patterns

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

Page 13: Java Script Patterns

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 !==!==

Page 14: Java Script Patterns

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”)

Page 15: Java Script Patterns

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 () {…}

Page 16: Java Script Patterns

Naming Convention

Camel case constructors functions methods variables: all lowercase words with underscore

Constants: use all capital letters Global variables: use all capital letters

Page 17: Java Script Patterns

Naming Convention

Private scope Underscore prefix(?)

e.g. _getName()_getName() properties methods

Page 18: Java Script Patterns

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

Page 19: Java Script Patterns

Literals and Constructors

Page 20: Java Script Patterns

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()

Page 21: Java Script Patterns

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

Page 22: Java Script Patterns

Array Literal

var array = [ ];var array = [ ]; Array.isArrayArray.isArray method

Added from ES5 Array toString()

[object Array] Object toString()toString()

[object Object]

Page 23: Java Script Patterns

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

Page 24: Java Script Patterns

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

Page 25: Java Script Patterns

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

Page 26: Java Script Patterns

Error Objects

Error()Error(), SyntaxError()SyntaxError(), TypeError()TypeError() name, message

Throw…Catch Custom error object

Page 27: Java Script Patterns

Constructor Syntax

Page 28: Java Script Patterns

Functions

Page 29: Java Script Patterns

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

Page 30: Java Script Patterns

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

Page 31: Java Script Patterns

Function

Function Declaration function function addadd() {…}() {…} Inside other functions or the global scope

Function’s name Pros

Debugging Recursive call

Page 32: Java Script Patterns

API Patterns

Help you provide better and cleaner interface to your functions Callback Pattern Configuration Objects Returning Functions Currying

Page 33: Java Script Patterns

Initialization Patterns

Help you perform initialization and setup tasks without polluting the global namespace Immediate Function Immediate Object Initialization Init-Time Branching

Page 34: Java Script Patterns

Performance Patterns

Help speed up the code Memoization Self-Defining Functions

Page 35: Java Script Patterns

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()

Page 36: Java Script Patterns

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

Page 37: Java Script Patterns

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

Page 38: Java Script Patterns

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

Page 39: Java Script Patterns

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

Page 40: Java Script Patterns

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?

Page 41: Java Script Patterns

Object Creation Patterns

Page 42: Java Script 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

Page 43: Java Script Patterns

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

Page 44: Java Script Patterns

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)

Page 45: Java Script Patterns

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

Page 46: Java Script Patterns

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

Page 47: Java Script Patterns

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

Page 48: Java Script Patterns

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

Page 49: Java Script Patterns

Static Members

No instance-specific Public Static member

Be accessible outside via Constructor

Private Static member Not accessible outside Using Closure feature

Page 50: Java Script Patterns

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)

Page 51: Java Script Patterns

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

Page 52: Java Script Patterns

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

Page 53: Java Script Patterns

Code Reuse Patterns

Page 54: Java Script 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

Page 55: Java Script Patterns

The Default Pattern (#1) Child.prototype = new Parent( );Child.prototype = new Parent( );

Page 56: Java Script Patterns

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

Page 57: Java Script Patterns

Rent-a-Constructor (#2) function Child (…) {function Child (…) {

Parent.apply(this, arguments); Parent.apply(this, arguments);}}

Page 58: Java Script Patterns

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

Page 59: Java Script Patterns

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( );

Page 60: Java Script Patterns

Rent and Set Prototype (#3)

Benefits Combine #1 and #2 patterns

Drawbacks Parent constructor is called twice Parent members get inherited twice

Page 61: Java Script Patterns

Share the Prototype (#4) Child.prototype = Parent.protoype;Child.prototype = Parent.protoype;

Page 62: Java Script Patterns

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

Page 63: Java Script Patterns

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;

Page 64: Java Script Patterns

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

Page 65: Java Script Patterns

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

Page 66: Java Script Patterns

Prototypal Inheritance function object (o) {function object (o) {

function F( ) { } function F( ) { } F.prototype = o; F.prototype = o; return new F( ); return new F( );}}

Page 67: Java Script Patterns

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);

Page 68: Java Script Patterns

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

Page 69: Java Script Patterns

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

Page 70: Java Script Patterns

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( )

Page 71: Java Script Patterns

Design Patterns

Page 72: Java Script 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

Page 73: Java Script Patterns

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(?)

Page 74: Java Script Patterns

Iterator

Purpose Providing an API to loop over and navigate

around a complex custom data structure Additional convenience methods

rewind( )rewind( ) current( )current( )

Page 75: Java Script Patterns

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

Page 76: Java Script Patterns

Decorator Implementation

Page 77: Java Script Patterns

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

Page 78: Java Script Patterns

Facade

Purpose Providing a more convenient API by wrapping co

mmon methods into a new one Handle browser events

stopPropagation( )stopPropagation( ) preventDefault( )preventDefault( )

Page 79: Java Script Patterns

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

Page 80: Java Script Patterns

Proxy As a Cache

Page 81: Java Script Patterns

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

Page 82: Java Script Patterns

Mediator in Keypress Game

Page 83: Java Script Patterns

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( )

Page 84: Java Script Patterns

DOM and Browser Patterns

Page 85: Java Script 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

Page 86: Java Script Patterns

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

Page 87: Java Script Patterns

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);

Page 88: Java Script Patterns

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;;

Page 89: Java Script Patterns

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;;

Page 90: Java Script Patterns

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

Page 91: Java Script Patterns

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);

Page 92: Java Script Patterns

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

Page 93: Java Script Patterns

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

Page 94: Java Script Patterns

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);

Page 95: Java Script Patterns

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

Page 96: Java Script Patterns

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

Page 97: Java Script Patterns

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

Page 98: Java Script Patterns

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>

Page 99: Java Script Patterns

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

Page 100: Java Script Patterns

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”

Page 101: Java Script Patterns

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

Page 102: Java Script Patterns

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

Page 103: Java Script Patterns

Conclusion

Q&A