Upload
chandan-jog
View
555
Download
2
Embed Size (px)
DESCRIPTION
The presentation covers Javascript Gotcha's and patterns to use while implementing client side browser applications.
Citation preview
JavaScript -‐ What’s in the language?
JavaScript as a language • Implementa3on of ECMASCRIPT • Object oriented • No Classes • Dynamic Objects -‐ collec3on of named proper3es. You can add, remove, update its members.
• Loose typing • lambdas • Na3ve and host objects -‐ Environment specific • Prototypical inheritance
Good Parts
• Lambda • Dynamic objects • Loose typing • Object literals
Bad Parts
• Global Variables • + adds and concatenates • Semicolon inser3on • typeof • with and eval • == and != • false, null, undefined, NaN
General Pa8erns
Minimizing global variables
/*#Title:#Minimizing#Globals#Description:#they#are#declared#outside#of#any#function#or#simply#used#without#being#declared!
# # # */!!! ! ! myglobal!=!"hello";!//#antipattern!! ! ! console.log(myglobal);!//#"hello"!! ! ! console.log(window.myglobal);!//#"hello"!! ! ! console.log(window["myglobal"]);!//#"hello"!! ! ! console.log(this.myglobal);!//#"hello"!!
Implied global variables
! ! ! //!antipatten!1!! ! ! function!sum(x,!y)!{!! ! ! ! //!implied!global!! ! ! ! result!=!x!+!y;!! ! ! ! return!result;!! ! ! }!!!! ! ! //!preferred!1!! ! ! function!sum(x,!y)!{!
//!a!variable!declared!inside!of!a!function!is!local!to!that!function!and!not!available!outside!the!function!
! ! ! ! var!result!=!x!+!y;!! ! ! ! return!result;!! ! ! }!!!!
! ! ! //"antipattern"2!! ! ! function!foo()!{!! ! ! ! var!a!=!b!=!0;!! ! ! ! //"...!! ! ! }!!! ! ! //"the"preceding"code"snippet"will"behave"as"if"you've"typed"the"following!! ! ! var!a!=!(b!=!0);!!!! ! ! //"preferred"2!! ! ! function!foo()!{!! ! ! ! var!a,!b;!! ! ! ! //"...!! ! ! ! a!=!b!=!0;!//"both"local!! ! ! }!!
Single var PaSern ! ! !!! ! ! /*!Benefits:!
!*!1.!Provides!a!single!place!to!look!for!all!the!local!variables!needed!by!the!function!
! ! ! !*!2.!Prevents!logical!errors!when!a!variable!is!used!before!it's!defined!! ! ! !*!3.!Helps!you!remember!to!declare!variables!and!therefore!minimize!globals!! ! ! */!!! ! ! function!func()!{!! ! ! ! var!a!=!1,!! ! ! ! ! ! b!=!2,!! ! ! ! ! ! sum!=!a!+!b,!! ! ! ! ! ! myobject!=!{},!! ! ! ! ! ! i,!! ! ! ! ! ! j;!!! ! ! ! //!function!body...!! ! ! }!!! ! ! function!updateElement()!{!! ! ! ! var!el!=!document.getElementById("result"),!! ! ! ! ! ! style!=!el.style;!! ! ! ! //!do!something!with!el!and!style...!! ! ! }!!
Namespacing
! ! ! //!unsafe!! ! ! var!MYAPP!=!{};!! ! ! //!better!! ! ! if!(typeof!MYAPP!===!"undefined")!{!! ! ! ! var!MYAPP!=!{};!! ! ! }!! ! ! //!or!shorter!! ! ! var!MYAPP!=!MYAPP!||!{};!!
! ! ! MYAPP.namespace!=!function!(ns_string)!{!! ! ! ! var!parts!=!ns_string.split('.'),!! ! ! ! ! ! parent!=!MYAPP,!! ! ! ! ! ! i;!!! ! ! ! //"strip"redundant"leading"global!! ! ! ! if!(parts[0]!===!"MYAPP")!{!! ! ! ! ! parts!=!parts.slice(1);!! ! ! ! }!!! ! ! ! for!(i!=!0;!i!<!parts.length;!i!+=!1)!{!! ! ! ! ! //"create"a"property"if"it"doesn't"exist!! ! ! ! ! if!(typeof!parent[parts[i]]!===!"undefined")!{!! ! ! ! ! ! parent[parts[i]]!=!{};!! ! ! ! ! }!! ! ! ! ! parent!=!parent[parts[i]];!! ! ! ! }!! ! ! ! return!parent;!! ! ! };!!! ! ! //"assign"returned"value"to"a"local"var!! ! ! var!module2!=!MYAPP.namespace('MYAPP.modules.module2');!! ! ! console.log(module2!===!MYAPP.modules.module2);!//"true!!!
Implied Typecas3ng: false, null, undefined, NaN
! ! ! var!zero!=!0;!!! ! ! /*#antipattern!# # # #*#JavaScript#implicitly#typecasts#variables#when#you#compare#them.!# # # #*#That's#why#comparisons#such#as#false#==#0#or#""#==#0#return#true.!# # # #*/!! ! ! if!(zero!==!false)!{!! ! ! ! //#this#block#is#executed...!! ! ! }!!!! ! ! //#preferred!! ! ! /*#To#avoid#confusion#caused#by#the#implied#typecasting,!
*#always#use#the#===#and#!==#operators#that#check#both#the#values#and#the#type#of#the#expressions#you#compare!
# # # */!! ! ! if!(zero!===!false)!{!! ! ! ! //#not#executing#because#zero#is#0,#not#false!! ! ! }!! !
Avoiding eval
! ! ! /*!Title:!Avoiding!eval()!! ! ! !*!Description:!avoid!using!eval()!! ! ! !*/!!! ! ! //!antipattern!1!! ! ! var!property!=!"name";!! ! ! alert(eval("obj."!+!property));!!!! ! ! //!preferred!1!! ! ! var!property!=!"name";!! ! ! alert(obj[property]);!!!
! ! ! /*#antipattern#2!*#It's#also#important#to#remember#that#passing#strings#to#setInterval(),#setTimeout(),!*#and#the#Function()#constructor#is,#for#the#most#part,#similar#to#using#eval()#and#therefore#should#be#avoided.!
# # # */!! ! ! setTimeout("myFunc()",!1000);!! ! ! setTimeout("myFunc(1,!2,!3)",!1000);!!!! ! ! //#preferred#2!! ! ! setTimeout(myFunc,!1000);!! ! ! setTimeout(function!()!{!! ! ! ! myFunc(1,!2,!3);!! ! ! },!1000);!! ! ! //#in#supported#browsers#(i.e.#not#IE)!! ! ! setTimeout(myFunc,!1000,!1,!2,!3);!!!
For-‐in loops ! ! ! /*#Title:#for-in#loops!# # # #*#Description:#optimized#for-in#loops!# # # #*/!!! ! ! //#the#object!! ! ! var!man!=!{!! ! ! ! hands:2,!! ! ! ! legs:2,!! ! ! ! heads:1!! ! ! };!!! ! ! //#somewhere#else#in#the#code!! ! ! //#a#method#was#added#to#all#objects!! ! ! if!(typeof!Object.prototype.clone!===!'undefined')!{!! ! ! ! Object.prototype.clone!=!function!()!{!! ! ! ! };!! ! ! }!!! !
! ! ! //"antipattern!! ! ! //"for,in"loop"without"checking"hasOwnProperty()!! ! ! for!(var!i!in!man)!{!! ! ! ! console.log(i,!":",!man[i]);!! ! ! }!! ! ! /*!" " " "*"result"in"the"console!" " " "*"hands":"2!" " " "*"legs":"2!" " " "*"hands":"1!" " " "*"clone:"function()!" " " "*/!!!! ! ! //"preferred"1!! ! ! for!(var!i!in!man)!{!! ! ! ! if!(man.hasOwnProperty(i))!{!//"filter!! ! ! ! ! console.log(i,!":",!man[i]);!! ! ! ! }!! ! ! }!!! ! ! /*!" " " "*"result"in"the"console!" " " "*"hands":"2!" " " "*"legs":"2!" " " "*"heads":"1!" " " "*/!!
Automa3c semicolon inser3on
//antipattern!return!{!!!!!status:!true!};!!//preferred!return{!!!!!status:!true!};!!
Func:on Pa8erns
Closures //"Your"setup"function"can"store"some"private"data"in"a"closure"and"use"that"data"somehow.!//"Here"setup()"creates"a"counter"function,"which"gives"a"next"ID"for"example."But"the"count"variable"is"not"exposed.!
!! ! ! var!setup!=!function!()!{!! ! ! ! var!count!=!0;!! ! ! ! return!function!()!{!! ! ! ! ! return!++count;!! ! ! ! };!! ! ! };!! ! ! //"usage!! ! ! var!next!=!setup();!! ! ! //next();"//"returns"1!! ! ! //next();"//"returns"2!! ! ! //next();"//"returns"3!!
Currying ! ! ! /***!# # # #currying!# # # #***/!!! ! ! //#a#curried#add()!! ! ! //#accepts#partial#list#of#arguments!! ! ! function!add(x,!y)!{!! ! ! ! var!oldx!=!x,!oldy!=!y;!! ! ! ! if!(typeof!oldy!===!"undefined")!{!//#partial!! ! ! ! ! return!function!(newy)!{!! ! ! ! ! ! return!oldx!+!newy;!! ! ! ! ! }!! ! ! ! }!! ! ! ! //#full#application!! ! ! ! return!x!+!y;!! ! ! }!!! ! ! //#test!! ! ! typeof!add(5);!//#"function"!! ! ! add(3)(4);!//#7!!
Literals, Constructors and Object crea:on Pa8erns
To ‘new’ or not ! ! ! ! !!! ! ! //!antipattern!! ! ! var!car!=!new!Object();!! ! ! car.goes!=!"far";!!!! ! ! //!preferred!! ! ! var!car!=!{goes:"far"};!!! ! ! //!constructor!! ! ! function!Waffle()!{!! ! ! ! this.tastes!=!"yummy";!! ! ! }!!! ! ! //!antipattern!! ! ! //!forgotten!`new`!! ! ! var!good_morning!=!Waffle();!! ! ! console.log(typeof!good_morning);!//!"undefined"!! ! ! console.log(window.tastes);!//!"yummy"!!!! ! ! //!preferred!! ! ! var!good_morning!=!new!Waffle();!! ! ! console.log(typeof!good_morning);!//!"object"!! ! ! console.log(good_morning.tastes);!//!"yummy"!!!! ! !!
PaSerns for enforcing ‘new’ ! ! ! !! ! ! function!Waffle()!{!! ! ! ! if!(!(this!instanceof!Waffle))!{!! ! ! ! ! return!new!Waffle();!! ! ! ! }!!! ! ! ! this.tastes!=!"yummy";!! ! ! }!!! ! ! var!good_morning!=!new!Waffle();!! ! ! var!good_evening!=!Waffle();!!! ! ! console.log(typeof!good_morning);!//""object"!! ! ! console.log(good_morning.tastes);!//""yummy"!! ! ! console.log(typeof!good_evening);!//""object"!! ! ! console.log(good_evening.tastes);!//""yummy"!!
! ! ! //!antipattern!! ! ! //!with!wrappers!! ! ! var!s!=!new!String("my!string");!! ! ! var!n!=!new!Number(101);!! ! ! var!b!=!new!Boolean(true);!!!! ! ! //!preferred!! ! ! //!without!wrappers!! ! ! var!s!=!"my!string";!! ! ! var!n!=!101;!! ! ! var!b!=!true;!!!
! ! ! /*!# # # #only#use#primitive#wrappers#when#you#want#to#augment#the#value#and#persist#state!# # # #*/!!! ! ! //#primitive#string!! ! ! var!greet!=!"Hello!there";!! ! ! //#primitive#is#converted#to#an#object!! ! ! //#in#order#to#use#the#split()#method!! ! ! greet.split('!')[0];!//#"Hello"!! ! ! //#attemting#to#augment#a#primitive#is#not#an#error!! ! ! greet.smile!=!true;!! ! ! //#but#it#doesn't#actually#work!! ! ! console.log(typeof!greet.smile);!//#"undefined"!!! ! ! //#primitive#wrapper!! ! ! var!greet!=!new!String("Hello!there");!! ! ! //#split()#method#is#called#directly#on#the#object!! ! ! greet.split('!')[0];!//#"Hello"!! ! ! //#augment#the#object!! ! ! greet.smile!=!true;!! ! ! console.log(typeof!greet.smile);!//#"boolean"!!
Module paSern MYAPP.utilities.array/=/(function/()/{// / / / //"private"properties// / / / var/array_string/=/"[object/Array]",// / / / ops/=/Object.prototype.toString,/// / / / //"private"methods// / / / inArray/=/function/(haystack,/needle)/{// / / / / for/(var/i/=/0,/max/=/haystack.length;/i/</max;/i/+=/1)/{// / / / / / if/(haystack[i]/===/needle)/{// / / / / / / return/i;// / / / / / }// / / / / }// / / / / return//1;// / / / },// / / / isArray/=/function/(a)/{// / / / / return/ops.call(a)/===/array_string;// / / / };// / / / //"end"var/// / / / //"revealing"public"API// / / / return/{// / / / / isArray:isArray,// / / / / indexOf:inArray// / / / };// / / }());/ !
Code Reuse Pa8erns
Prototypal Inheritance
! ! ! function!object(o)!{!! ! ! ! function!F()!{!! ! ! ! }!!! ! ! ! F.prototype!=!o;!! ! ! ! return!new!F();!! ! ! }!!! ! ! //"object"to"inherit"from!! ! ! var!parent!=!{!! ! ! ! name:"Papa"!! ! ! };!!! ! ! //"the"new"object!! ! ! var!child!=!object(parent);!!! ! ! //"testing!! ! ! console.log(child.name);!//""Papa"!!! !
! ! ! //"parent"constructor!! ! ! function!Person()!{!! ! ! ! //"an""own""property!! ! ! ! this.name!=!"Adam";!! ! ! }!! ! ! //"a"property"added"to"the"prototype!! ! ! Person.prototype.getName!=!function!()!{!! ! ! ! return!this.name;!! ! ! };!! ! ! //"create"a"new"person!! ! ! var!papa!=!new!Person();!! ! ! //"inherit!! ! ! var!kid!=!object(papa);!! ! ! //"test"that"both"the"own"property!! ! ! //"and"the"prototype"property"were"inherited!! ! ! console.log(kid.getName());!//""Adam"!!
Augmen3ng built-‐in Prototypes
! ! ! if!(typeof!Object.prototype.myMethod!!==!"function")!{!! ! ! ! Object.prototype.myMethod!=!function!()!{!! ! ! ! ! //"implementation...!! ! ! ! };!! ! ! }!!
Design Pa8erns
CREATIONAL
Builder constructs complex objects by separa3ng construc3on and representa3on
Factory Method creates objects without specifying the exact class to create
Singleton restricts object crea3on for a class to only one instance
STRUCTURAL
Decorator dynamically adds/overrides behavior in an exis3ng method of an object
Facade provides a simplified interface to a large body of code
BEHAVIORAL
Chain of responsibility delegates commands to a chain of processing objects
Command creates objects which encapsulate ac3ons and parameters
Mediator allows loose coupling between classes by being the only class that has detailed knowledge of their methods
Observer is a publish/subscribe paSern which allows a number of observer objects to see an event
Composite
//"Single"elements!$("#singleItem").addClass("active");!$("#container").addClass("active");!!//"Collections"of"elements!$("div").addClass("active");!$(".item").addClass("active");!$("input").addClass("active");!!
Adapter
//"Cross"browser"opacity:!//"opacity:"0.9;""Chrome"4+,"FF2+,"Saf3.1+,"Opera"9+,"IE9,"iOS"3.2+,"Android"2.1+!//"filter:"alpha(opacity=90);""IE6KIE8!!//"Setting"opacity!$(".container").css({!opacity:.5!});!!//"Getting"opacity!var!currentOpacity!=!$(".container").css('opacity');! !
Observer
//"Equivalent"to"subscribe(topicName,"callback)!$(document).on("topicName",!function!()!{!!!!!//..perform"some"behaviour!});!!//"Equivalent"to"publish(topicName)!$(document).trigger("topicName");!!//"Equivalent"to"unsubscribe(topicName)!$(document).off("topicName");! !
AMD -‐ Asynchronous module defini3on
define('''''module_id'/*optional*/,'''''[dependencies]'/*optional*/,'''''definition'function'/*function-for-instantiating-the-module-or-object*/')'!!!require(["foo",'"bar"],'function'(foo,'bar)'{'''''//-rest-of-your-code-here'''''foo.doSomething();'});'!
Prolifera3on of MV* frameworks
Prolifera3on of MV* frameworks
• Rich internet single page applica3ons • Data Binding • Client side templates • Client-‐Centric or Server-‐Centric-‐ that is the ques3on.
• Minify, concatenate, compress • Load scripts at the end of pages • Sta3c code analysis using Jslint/Jshint • Tes3ng your code – Jasmine, Phantomjs etc
References
Ques:ons?