JavaScript: Advanced Scoping & Other Puzzles

89
Monday, November 15, 2010

description

In this session, we'll review the fundamentals of Javascript variable scope and common "execution context" (scope) challenges associated with early/late binding of event handlers, specifically within complex Ext JS layouts. We'll also bring several patterns (namespaced references, Function closures, inline references, ref/refOwner, and the "Poor-man's message bus") to bear on the bowl of soup we call "scope."

Transcript of JavaScript: Advanced Scoping & Other Puzzles

Page 1: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 2: JavaScript: Advanced Scoping & Other Puzzles

Doug Hendricks

Solutions ArchitectSencha Services

Monday, November 15, 2010

Page 3: JavaScript: Advanced Scoping & Other Puzzles

ECMAScope Soup

‘From the can’, alternate recipes,

and puzzles.

Monday, November 15, 2010

Page 4: JavaScript: Advanced Scoping & Other Puzzles

• ECMA Javascript variables and scope

• In the can: Activation objects, scope chains, name resolution, and execution context

• Too much salt (common mistakes)

• Ext Observable binding contexts

• Alternate binding approaches for Ext Components

On the menu:

Monday, November 15, 2010

Page 5: JavaScript: Advanced Scoping & Other Puzzles

Global variables - exist throughout the life of a script. Also considered public, they are:

those NOT declared within a function block

declared ANYWHERE in your script without the var keyword

<script type="text/javascript"> globalB = 4;

var globalA = 3, say = console.log;</script>

Global Variables

Monday, November 15, 2010

Page 6: JavaScript: Advanced Scoping & Other Puzzles

What is the global object(namespace)?

Browsers, GreaseMonkey : window

HTML5 Workers, Node.Js : global

Monday, November 15, 2010

Page 7: JavaScript: Advanced Scoping & Other Puzzles

<script type="text/javascript"> globalB = 4;

var globalA = 3, say = console.log;</script>

or, referenced through the global object as:window.globalAwindow.say

Global Variables

Monday, November 15, 2010

Page 8: JavaScript: Advanced Scoping & Other Puzzles

Local variables - survive only as long as the Function block they are declared in has an execution context.

Local Variables

<script type="text/javascript"> var globalA, say = console.log;

function doIt ( ) { var localA = 5; //local scope only } </script>

Monday, November 15, 2010

Page 9: JavaScript: Advanced Scoping & Other Puzzles

<script type="text/javascript"> var globalA, say = console.log,

a = 4; doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } </script>

Something wrong here?

Monday, November 15, 2010

Page 10: JavaScript: Advanced Scoping & Other Puzzles

<script type="text/javascript"> var globalA, say = console.log,

a = 4; doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } </script>

Something wrong here?

Monday, November 15, 2010

Page 11: JavaScript: Advanced Scoping & Other Puzzles

<script type="text/javascript"> var globalA, say = console.log,

a = 4; doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } </script>

Something wrong here?

<- this can’t work!

<- this is 4, right?

Monday, November 15, 2010

Page 12: JavaScript: Advanced Scoping & Other Puzzles

<script type="text/javascript"> var globalA, say = console.log,

a = 4; doIt(); <- sure it does, why? function doIt ( ) {

say ( a ); <- undefined! why? var a = 5; say( ++a ); } </script>

Monday, November 15, 2010

Page 13: JavaScript: Advanced Scoping & Other Puzzles

introducing...

activation objects,scope chain,

identifier resolution

Monday, November 15, 2010

Page 14: JavaScript: Advanced Scoping & Other Puzzles

Execution context initialized containing a ‘root’ or global object.

Monday, November 15, 2010

Page 15: JavaScript: Advanced Scoping & Other Puzzles

Execution context initialized containing a ‘root’ or global object.

<script type="text/javascript"> var globalA, say = console.log, a = 4; doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } </script>

global

window : objectdocument : objectnavigator : object

a : 4doIt : function

globalA : undefinedsay : function

Scope chain

Monday, November 15, 2010

Page 16: JavaScript: Advanced Scoping & Other Puzzles

next, an activation object is prepended to the scope-chain by first scanning the function body for local var’s:

globalwindow : object

document : objectnavigator : object

a : 4doIt : function

globalA : undefined

Monday, November 15, 2010

Page 17: JavaScript: Advanced Scoping & Other Puzzles

next, an activation object is prepended to the scope-chain by first scanning the function body for local var’s:

doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

activationarguments : []this : windowa : undefined

Scope chain

thus, a new context is created for doIt, containing a local ‘a’

globalwindow : object

document : objectnavigator : object

a : 4doIt : function

globalA : undefined

Monday, November 15, 2010

Page 18: JavaScript: Advanced Scoping & Other Puzzles

Identifier resolution: get me ‘say’ ! (the hunt begins)

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4say : function

activationarguments : []this : windowa : undefined

Scope chain

Monday, November 15, 2010

Page 19: JavaScript: Advanced Scoping & Other Puzzles

Identifier resolution: get me ‘say’ ! (the hunt begins)

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4say : function

activationarguments : []this : windowa : undefined

Scope chain

local?, nope!

Monday, November 15, 2010

Page 20: JavaScript: Advanced Scoping & Other Puzzles

Identifier resolution: get me ‘say’ ! (the hunt begins)

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4say : function

activationarguments : []this : windowa : undefined

Scope chain

local?, nope!

global has it!

Monday, November 15, 2010

Page 21: JavaScript: Advanced Scoping & Other Puzzles

Now, on to the function argument: ‘a’

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } global

window : objectdocument : objectnavigator : object

a : 4 say : function

activationarguments : []this : windowa : undefined

Scope chain

Monday, November 15, 2010

Page 22: JavaScript: Advanced Scoping & Other Puzzles

Now, on to the function argument: ‘a’

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); } global

window : objectdocument : objectnavigator : object

a : 4 say : function

activationarguments : []this : windowa : undefined

Scope chain

<- prints: undefined<- NOT 5!

Monday, November 15, 2010

Page 23: JavaScript: Advanced Scoping & Other Puzzles

Now, on to assignment...

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4 say : function

activationarguments : []this : windowa : undefined

Scope chain

Monday, November 15, 2010

Page 24: JavaScript: Advanced Scoping & Other Puzzles

Now, on to assignment...

function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4 say : function

activationarguments : []this : windowa : undefined

Scope chain

local? yes, set it!

and so on...

activationarguments : []this : window

a : 5

Monday, November 15, 2010

Page 25: JavaScript: Advanced Scoping & Other Puzzles

When function doIt is completed, it’s execution context (scope chain) is destroyed:

doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

globalwindow : object

document : objectnavigator : object

a : 4 say : function

activationarguments : []this : window

a : 5

Scope chain

Monday, November 15, 2010

Page 26: JavaScript: Advanced Scoping & Other Puzzles

When function doIt is completed, it’s execution context (scope chain) is destroyed:

doIt(); function doIt ( ) {

say ( a ); var a = 5; say( ++a ); }

and life continues, until the next function block...

Monday, November 15, 2010

Page 27: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 28: JavaScript: Advanced Scoping & Other Puzzles

Extra fat ?(Scope Chain Augmentation)

Monday, November 15, 2010

Page 29: JavaScript: Advanced Scoping & Other Puzzles

(Scope Chain Augmentation)

Monday, November 15, 2010

Page 30: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentation

The big offenders:

Monday, November 15, 2010

Page 31: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentation

Closures

with Clause

catch clause of try/catch

The big offenders:

Monday, November 15, 2010

Page 32: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain AugmentationFunction Closures

var trimString = function () { var reReplace = /^\s+|\s+$/g;

return ( function (str){ return str.replace(reReplace, ‘’);

} );}( ); <- create the closure

globalwindow : object

document : objectnavigator : object

Monday, November 15, 2010

Page 33: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain AugmentationFunction Closures

var trimString = function () { var reReplace = /^\s+|\s+$/g;

return ( function (str){ return str.replace(reReplace, ‘’);

} );}( ); <- create the closure

activationarguments : []this : window

reReplace : RegExp

globalwindow : object

document : objectnavigator : object

activationarguments : [str]this : window

Monday, November 15, 2010

Page 34: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain AugmentationFunction Closures

var trimString = function () { var reReplace = /^\s+|\s+$/g;

return ( function (str){ return str.replace(reReplace, ‘’);

} );}( ); <- create the closure

activationarguments : []this : window

reReplace : RegExp

globalwindow : object

document : objectnavigator : object

activationarguments : [str]this : window

Closures will always have 3 scope chain members,

minimum!Monday, November 15, 2010

Page 35: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain AugmentationFunction Closures

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

els.removeClass(‘puff’); els.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

globalwindow : object

document : objectnavigator : object

Monday, November 15, 2010

Page 36: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain AugmentationFunction Closures

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

els.removeClass(‘puff’); els.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

activationarguments : []this : window

els : Ext.CompositeEl...doc : Ext.Element

globalwindow : object

document : objectnavigator : object

activationarguments : [e, target]

this : Ext.Element

Monday, November 15, 2010

Page 37: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 38: JavaScript: Advanced Scoping & Other Puzzles

Even more fat !?(with Clause)

Monday, November 15, 2010

Page 39: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 40: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentation‘with’ Clause

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

with (els) {removeClass(‘puff’);

highlight();}

}, ‘delegate’ : 'div.puff', ‘single’ : true });}

Monday, November 15, 2010

Page 41: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentation‘with’ Clause

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

with (els) {removeClass(‘puff’);

highlight();}

}, ‘delegate’ : 'div.puff', ‘single’ : true });}

activationarguments : []

globalwindow : object

activationarguments : [e, target]

Monday, November 15, 2010

Page 42: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentation‘with’ Clause

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

with (els) {removeClass(‘puff’);

highlight();}

}, ‘delegate’ : 'div.puff', ‘single’ : true });}

activationarguments : []

globalwindow : object

activationarguments : [e, target]

variableels : Ext.CompositeEl...

Monday, November 15, 2010

Page 43: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 44: JavaScript: Advanced Scoping & Other Puzzles

Let’s just eat Lard !(catch in try/catch)

Monday, November 15, 2010

Page 45: JavaScript: Advanced Scoping & Other Puzzles

Monday, November 15, 2010

Page 46: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentationcatch block

doc.on({ 'click' : function(e, target){

try{ with (els) {

removeClass(‘puff’); highlight();

}

} catch( err ) { Ext.MessageBox.alert(‘Ooops’);}

},

Monday, November 15, 2010

Page 47: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentationcatch block

doc.on({ 'click' : function(e, target){

try{ with (els) {

removeClass(‘puff’); highlight();

}

} catch( err ) { Ext.MessageBox.alert(‘Ooops’);}

},

activationarguments : []

globalwindow : object

activationarguments : [e, target]

Monday, November 15, 2010

Page 48: JavaScript: Advanced Scoping & Other Puzzles

Scope Chain Augmentationcatch block

doc.on({ 'click' : function(e, target){

try{ with (els) {

removeClass(‘puff’); highlight();

}

} catch( err ) { Ext.MessageBox.alert(‘Ooops’);}

},

activationarguments : []

globalwindow : object

activationarguments : [e, target]

variablearguments : [err]

Monday, November 15, 2010

Page 49: JavaScript: Advanced Scoping & Other Puzzles

Optimizations

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

els.removeClass(‘puff’); els.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

Monday, November 15, 2010

Page 50: JavaScript: Advanced Scoping & Other Puzzles

Optimizations

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

els.removeClass(‘puff’); els.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

Expensive

Monday, November 15, 2010

Page 51: JavaScript: Advanced Scoping & Other Puzzles

Optimizations

function puffEmUp () {

var E = Ext, els = E.select('div');

els.addClass('puff');

E.getDoc().on({ 'click' : function(e, target){

var collect = els;collect.removeClass(‘puff’);

collect.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

function puffEmUp () { var els = Ext.select('div'), doc = Ext.getDoc();

els.addClass('puff'); doc.on({ 'click' : function(e, target){

els.removeClass(‘puff’); els.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

Expensive Better

Monday, November 15, 2010

Page 52: JavaScript: Advanced Scoping & Other Puzzles

Optimize Furtherfunction puffEmUp () { var E = Ext,

els = E.select('div');

els.addClass('puff'); E.getDoc().on({ 'click' : function(e, target){

try{

this.removeClass(‘puff’);

this.highlight(); } catch (err) { // a compromise E.MessageBox.alert(‘Oops’); }

},

‘scope’ : els, ‘delegate’ : 'div.puff', ‘single’ : true });}

function puffEmUp () {

var E = Ext, els = E.select('div');

els.addClass('puff');

E.getDoc().on({ 'click' : function(e, target){

var collect = els;collect.removeClass(‘puff’);

collect.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

Monday, November 15, 2010

Page 53: JavaScript: Advanced Scoping & Other Puzzles

Optimize Furtherfunction puffEmUp () { var E = Ext,

els = E.select('div');

els.addClass('puff'); E.getDoc().on({ 'click' : function(e, target){

try{

this.removeClass(‘puff’);

this.highlight(); } catch (err) { // a compromise E.MessageBox.alert(‘Oops’); }

},

‘scope’ : els, ‘delegate’ : 'div.puff', ‘single’ : true });}

Betterfunction puffEmUp () {

var E = Ext, els = E.select('div');

els.addClass('puff');

E.getDoc().on({ 'click' : function(e, target){

var collect = els;collect.removeClass(‘puff’);

collect.highlight(); }, ‘delegate’ : 'div.puff', ‘single’ : true });}

Monday, November 15, 2010

Page 54: JavaScript: Advanced Scoping & Other Puzzles

Leverage Execution Contextfunction puffEmUp () {

var E = Ext,

els = E.select('div');

els.addClass('puff'); E.getDoc().on({ 'click' : function(e, target){

try{ this.removeClass(‘puff’);

this.highlight(); } catch (err) { // a compromise E.MessageBox.alert(‘Oops’); }

},

‘scope’ : els, ‘delegate’ : 'div.puff', ‘single’ : true });}

Monday, November 15, 2010

Page 55: JavaScript: Advanced Scoping & Other Puzzles

Leverage Execution Contextfunction puffEmUp () {

var E = Ext,

els = E.select('div');

els.addClass('puff'); E.getDoc().on({ 'click' : function(e, target){

try{ this.removeClass(‘puff’);

this.highlight(); } catch (err) { // a compromise E.MessageBox.alert(‘Oops’); }

},

‘scope’ : els, ‘delegate’ : 'div.puff', ‘single’ : true });}

Replace scope-chain traversal with a single context (this)

prototype search.

Monday, November 15, 2010

Page 56: JavaScript: Advanced Scoping & Other Puzzles

Recommendations

Declare frequently used function variables as locals.

Promote frequently used globals UP the scope chain (creating local references to them as necessary)

Use closures and try/catch handlers sparingly.

Forget about the ‘with’ clause! (deprecated in ECMA Javascript 5)

Monday, November 15, 2010

Page 57: JavaScript: Advanced Scoping & Other Puzzles

Why is this important at all?

Monday, November 15, 2010

Page 58: JavaScript: Advanced Scoping & Other Puzzles

trivia time!

Monday, November 15, 2010

Page 59: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

trivia time!

Monday, November 15, 2010

Page 60: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Monday, November 15, 2010

Page 61: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Is it:

Monday, November 15, 2010

Page 62: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Is it:

a: at least 2900

Monday, November 15, 2010

Page 63: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Is it:

a: at least 2900b: at least 5300

Monday, November 15, 2010

Page 64: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Is it:

a: at least 2900b: at least 5300c: at least 8800

Monday, November 15, 2010

Page 65: JavaScript: Advanced Scoping & Other Puzzles

Can you guess how manyfunction definitions there are in the

Ext 3.3 framework?

Is it:

a: at least 2900b: at least 5300c: at least 8800d: omg! I can’t count that high !

Monday, November 15, 2010

Page 66: JavaScript: Advanced Scoping & Other Puzzles

If you guessed:

b: at least 5300...

Monday, November 15, 2010

Page 67: JavaScript: Advanced Scoping & Other Puzzles

If you guessed:

b: at least 5300...

Monday, November 15, 2010

Page 68: JavaScript: Advanced Scoping & Other Puzzles

If you guessed:

b: at least 5300...

You’re Correct! but, you can’t leave early!

Monday, November 15, 2010

Page 69: JavaScript: Advanced Scoping & Other Puzzles

Common Mistakes and Bottlenecks

Monday, November 15, 2010

Page 70: JavaScript: Advanced Scoping & Other Puzzles

Where did it go?

<script type="text/javascript">

function doIt ( ) { var a = 5; say( ++a ); }

setTimeout( ‘doIt();‘ , 1000);

</script>

Monday, November 15, 2010

Page 71: JavaScript: Advanced Scoping & Other Puzzles

Where did it go?

<script type="text/javascript"> function doIt ( ) { var a = 5; say( ++a ); } setTimeout( ‘doIt();‘ , 1000); </script>

<script type="text/javascript"> var doIt = function ( ) { var a = 5; say( ++a ); }

setTimeout( ‘doIt();‘ , 1000); </script>

Monday, November 15, 2010

Page 72: JavaScript: Advanced Scoping & Other Puzzles

Where did it go?

<script type="text/javascript"> function doIt ( ) { var a = 5; say( ++a ); } setTimeout( ‘doIt();‘ , 1000); </script>

<script type="text/javascript"> var doIt = function ( ) { var a = 5; say( ++a ); }

setTimeout( ‘doIt();‘ , 1000); </script>

create a global reference!

Monday, November 15, 2010

Page 73: JavaScript: Advanced Scoping & Other Puzzles

Identifier Resolution Mayhem!

var getAddress = function(){ return (

some.favorite.customer.we.love.name + ‘\n’ + some.favorite.customer.we.love.address1 + ‘\n’ + some.favorite.customer.we.love.address2 + ‘\n’ + some.favorite.customer.we.love.city + ‘\n’ + some.favorite.customer.we.love.state + ‘\n’ + some.favorite.customer.we.love.zip );

};

Monday, November 15, 2010

Page 74: JavaScript: Advanced Scoping & Other Puzzles

Identifier Resolution Mayhem!

var getAddress = function(){ return (

some.favorite.customer.we.love.name + ‘\n’ + some.favorite.customer.we.love.address1 + ‘\n’ + some.favorite.customer.we.love.address2 + ‘\n’ + some.favorite.customer.we.love.city + ‘\n’ + some.favorite.customer.we.love.state + ‘\n’ + some.favorite.customer.we.love.zip );

};Don’t be a copy/paste victim !

Monday, November 15, 2010

Page 75: JavaScript: Advanced Scoping & Other Puzzles

Identifier Resolution Optimized!

var getAddress = function () { //resolve the global once! var cust = some.favorite.customer.we.love; return [

cust.name,cust.address1,cust.address2,cust.city,cust.state,cust.zip].join(‘\n’);

}; Monday, November 15, 2010

Page 76: JavaScript: Advanced Scoping & Other Puzzles

Iteration (with calories)Function-based Ext.each (iterable, function)Ext.iterate (iterable, function)$each$jQuery.each( iterable, function )Enumerable.each( iterable, function )Array.forEach(function)

Monday, November 15, 2010

Page 77: JavaScript: Advanced Scoping & Other Puzzles

Iteration (with calories)Function-based Ext.each (iterable, function)Ext.iterate (iterable, function)$each$jQuery.each( iterable, function )Enumerable.each( iterable, function )Array.forEach(function)

These iterators create additional scope chains.Reserve for light-duty use only!

Monday, November 15, 2010

Page 78: JavaScript: Advanced Scoping & Other Puzzles

Traditional event binding strategies

Monday, November 15, 2010

Page 79: JavaScript: Advanced Scoping & Other Puzzles

{xtype: ‘grid’,store : ‘storeId’,buttons : [{ text : ‘Remove Item’, handler : function(){..} , scope : ??? },{ text : ‘Close’, handler : function(){..}, scope: ??? }]}

Classic Quandary

Monday, November 15, 2010

Page 80: JavaScript: Advanced Scoping & Other Puzzles

{xtype: ‘grid’,store : ‘storeId’,

initComponent : function(){ //template method this.buttons = [{ text : ‘Remove Item’, iconCls : ‘remove-icon’, handler : this.removeItem , scope : this },{ text : ‘Close’, handler : this.destroy, scope : this }];

this.constructor.prototype.initComponent.call(this); },

removeItem : function(button){ var record = this.getSelectionModel().getSelected();

....... //remove the entity... }}

Monday, November 15, 2010

Page 81: JavaScript: Advanced Scoping & Other Puzzles

{xtype: ‘grid’,store : ‘storeId’,

initComponent : function(){ //template method this.buttons = [{ text : ‘Remove Item’, iconCls : ‘remove-icon’, handler : this.removeItem , scope : this },{ text : ‘Close’, handler : this.destroy, scope : this }];

this.constructor.prototype.initComponent.call(this); },

removeItem : function(button){ var record = this.getSelectionModel().getSelected();

....... //remove the entity... }}

Bring your desired scope into context(without sub-classing)

Monday, November 15, 2010

Page 82: JavaScript: Advanced Scoping & Other Puzzles

Poor-man’s Message Bus

Revised version of Ext.util.Observable class

Mechanism to loosely-couple behaviors using events (messaging)

Event binding complexity reduced for most situations.

Monday, November 15, 2010

Page 83: JavaScript: Advanced Scoping & Other Puzzles

(function(){

      Ext.extend(          Ext.ux.MsgBus = function(config){               this.events = {};               Ext.apply(this,config||{});               Ext.ux.MsgBus.superclass.constructor.call(this);            },               Ext.util.Observable,

         {            publish : function(topic /* ,variable arguments ,,, */  ){                 var t = String(topic);                 this.events[t] || (this.addEvents(t));                 return this.fireEvent.apply(

this, [t].concat(Array.prototype.slice.call(arguments,1))

);            }        }

);       var uxp = Ext.ux.MsgBus.prototype;       Ext.apply(uxp,{          subscribe    : uxp.on,      //aliases          unsubscribe  : uxp.un,          destroy      : uxp.purgeListeners       });

})();

Follow along at: http://www.sencha.com/forum/showthread.php?42942

Monday, November 15, 2010

Page 84: JavaScript: Advanced Scoping & Other Puzzles

Why not as a singleton?

Poor candidates for Unit testing as ‘state’ is unpredictable over time, cannot be reset.

Inhibits implementation flexibility.

The class can be extended/overloaded further to handle custom messaging behaviors.

Monday, November 15, 2010

Page 85: JavaScript: Advanced Scoping & Other Puzzles

Basic ux.MsgBus sampleExt.ns('your');your.bus = new Ext.ux.MsgBus();

your.bus.subscribe('test',       function(){ console.log(arguments); },      context,      {single:true, delay: 500 }    

//standard Observable arguments and options    );

var wasCancelled = (your.bus.publish('test', 'this is only a test', someObj, someArray) === false); 

Monday, November 15, 2010

Page 86: JavaScript: Advanced Scoping & Other Puzzles

Multi-ChannelExt.namespace('your');your.bus = {

channels: { // slots, topics (call it what you will) chat : new Ext.ux.MsgBus(),

feeds : new Ext.ux.MsgBus(),orders : new Ext.ux.MsgBus()},

destroy : function(){Ext.iterate(this.channels, Ext.destroy);

}};

var channels = your.bus.channels;your.control = { removeItem : function(itemRecord){

var success;//handle order removal centrally here (via data.Store, Ajax, etc)success ? channels.orders.publish(‘itemremoved’, itemRecord) : channels.orders.publish(‘itemremovalfailure’, itemRecord, response);

}};

channels.orders.subscribe({'remove' : your.control.removeItem,‘cancel’ : your.control.cancelOrder

});     

Monday, November 15, 2010

Page 87: JavaScript: Advanced Scoping & Other Puzzles

{xtype: ‘grid’,store : ‘storeId’,initComponent : function(){ //template method this.buttons = [{ text : ‘Remove Item’, iconCls : ‘remove-icon’, handler : this.removeItem , scope : this },{ text : ‘Close’, handler : this.destroy, scope : this }]; this.constructor.prototype.initComponent.call(this); },

removeItem : function(button){ var record = this.getSelectionModel().getSelected(), CB = function( success) {

success && button.enable(); };

channels.orders.publish(‘remove’, record, CB ); }}

Monday, November 15, 2010

Page 88: JavaScript: Advanced Scoping & Other Puzzles

Questions ?

Monday, November 15, 2010

Page 89: JavaScript: Advanced Scoping & Other Puzzles

Thank You!

Hackathon : 4:30pm

Enjoy the remainder of Senchacon 2010

Monday, November 15, 2010