WHAT: this is a blog where i collect news about the usage of javascript a serious programming language on the client side and server side. WHY: because it seams to be the most ubiquitous language and has functions as first class objects, and closures and ....

Friday, July 18, 2008

Reduce the number of inner function creations and closures

Oft it is easy to create an anonymous function to handle an event or perfrom a little task:

Look at this example:

var b = function (/*array*/a ) {
a.forEach(function(_){ if( _=_.text) alert(_);});
}


The function which perfroms the alert is in javascript an object and created once for the whole array but it is still created each time when b is called.

Functions are objects with a state fromed by a closure.
In this case the closure is not needed, as the function does not use any variable or parameter of b.
The new creation of this function on each call of x is thus just a waste of time and has to be cleaned up by garbage collection.

Wy not create the function once and store the function and reuse it lateron. But where?!

We could use the function object which we store in b.
To reference it we give it a name F
and our anonymous alert function is stored in F.alert_text:


var b = function F () {
a.forEach( F.alert_text = F. alert_text || function(_){ if( _=_.text) alert(_);});
}


It looks almost the same, but this time for each is perfomed with F.alert_text which is set to it's previous value or set to the anonymous function if not yet defined.

When we have a little global update function to extend (X) an object with properties of an other one like this:

var X = function(/*target*/t,/*source*/s){ for ( var p in s ) {t[p]=s[p];} return t; };


we can rewrite the above code to:

var b = X( function F () {
a.forEach( F.alert_text );
},{
alert_text : function(_){ if( _=_.text) alert(_);}
});


This time F.alert_text is even not tested and set to the same vaue, each time when b is called.

Note: this tip is only usefull if the extracted function (here alert_text) is really independent of the state defined by the function calling it. ( here b).

Anonymus temporary variables: _,__

A post on ajaxian about this blog entry by Michal Till and a especially a comment by Andrea Giammarch delivered the idea for this blog entry:

When we write code we often do repeat in our code property lookups over and over

Example:
 
if( node && node.nextSibling && node.nextSibling.className=='x' ) return node.nextSibling.className;



We can use an extra variable to make the code much sorter, cleaner and even faster:
Simply declare some anonymous temporary variables at the beginning of your function
 
function(..) { var _,__;


Use them where ever you like:
 
if (_=node) if(_=_.nextSibling) if((_=_.className)=='x') return _;

_=a;a=b;b=_ // swap


Why '_' ? Well because it is almost not visible. It's a perfect name for a temporary placeholder, the name is just not relevant, the meaning is revealed by it's immediate context.

Look at the next loop over an array to perfrom an alert for each element with a text property:
 
for( var i=0, l=a.length; i<l;i++) if (a[i].text) alert(a[i].text);


We could use _ like this:

 
for( var i=0,l=a.length;_=a[i],i<l;i++) if(_=_.text) alert(_);


Or in a more extreme way:
 
for(__=a,___=0,____=__.length;_=__[___],___<____;___++) if( _=_.text) alert(_);


While this is a lot longer, when we remove the punctation it is just for a 0 length if text alert and thus emphasizes the important elements.

Whereas the version with 'i,l' was for var i 0 l a length i l i if a i text alert a i text and our brain has to filter it.

Of course as an experienced programmer you are used to the i,l,i++ etc. and you will recognize it as a typical loop pattern,

But with the _ vars we express it more explicit: don't care about that looping stuff. You can copy it and replace 'a' and it will work. We could get used to this pattern as well and it may be a help for beginners.

Or we use the new forEach:

 
a.forEach(function(_){ if( _=_.text) alert(_);});


Oh this creates a new function each time the loop is used, but that's a topic for the next blog entry ;-)

Tuesday, July 1, 2008

Extending Javascript the easy way!!

Ometa by Alessandro Warth is a great environment, a must see!

Think of extending javascript with some little language extensions?
Writing a new / extending an existing compiler gives you a headache?
With OMeta/JS you can do it right in your javascript code:

Extend the Ometa Javascript parser (JSParser implemented in javascript) with a lets say say statement: Here it just does an alert();
Then switch the translator an execute the your new Javascript language right there:


eval(readFile('Compiled_JavaScript_Compiler'))

ometa EJSParser <: JSParser {
isKeyword :x = ?(x == 'say') | super(`isKeyword, x),
stmt = "say" expr:x sc -> ["call", ["get", "alert"], x]
| super("stmt")
}
EJSParser.matchAll("if (true) say 1+1", "stmt")

oldTranslateCode = translateCode

translateCode = function(s) {
var tree = EJSParser.matchAll(s, "topLevel")
var code = JSTranslator.match(tree, "trans")
return code
}

// evaluate the next statement in a different "do-it" than the above
say "hello world"

translateCode = oldTranslateCode



Some said Lively Kernel uses it. Well svg is nice. But why not stay with DOM nodes and be portable...

Parsing Javascript, Parsing with Javascript 2

Javascript parser/interpreter in javascript: Narcissus

Some other stuff on parsers in javascript: Parser Combinations

An own parser language in javascript OMeta