My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Saturday, May 28, 2011

My Last Comments On JSLint

Preface

I have been working with many teams and I have used JSLint on daily basis. This post is not about the tool itself, neither against Douglas work, this post is about developers often too religious about this tool.
Finally, if you follow this blog you have already read tons of other reasons to think rather than "suffer silently this tool".
It's my last post about it and I hope "it will not hurt your feelings".


Seriously guys, it's not that I think JSLint is all bad, but I cannot stop thinking it's simply an effect.
The more I hear or read about developers being so religious about this tool, the more I feel to blame it.
I am pretty sure Douglas will hate me for this post but I really hope he will read it 'till the end.

Douglas Talk At Falsy Values

Both me and big Doug were there, me for a workshop and Mr D. for his speech.
"Surprisingly" Mr Crockford talked about JSLint (again?!) and why it's so good.
While many hints for newcomers are absolutely a must know, many others are absolutely inconsistent for senior JavaScript developers.
There is a particular slide and a particular sentence Douglas said there:
... write code the way it's meant for the language ...

Above sentence was related to variables declaration, showing behind something similar to this classic example:

(function () {
// never executed
if (false) {
var something = 123;
}
}());

As all of us know, and if not we should, the reason JSLint would like to have all variables defined on top of the function is that no matter which condition, for or while loop, we have at some point, the parser will pre-consider all var in the same scope as local scope variables available since the very beginning.

(function () {
// there is no "var" in this scope
alert(something);
// throws "Can't find variable: something"
if (false) {
// eventually global in ES3 and ES5 with no strict
something = 123;
}
}());

The moment we define a variable local, even if we never reach that line, that variable is available for the whole scope, got it?

(function () {
alert(something);
// undefined and no errors
if (false) {
var something = 123;
}
}());

Good, now ...

JSLint Inconsistencies

Since the previous point is clear to everybody, I wonder if it's clear that function declaration has even more precedence than variables.

(function () {
alert(something);
// the function declared later on

function something() {
return 123;
}
}());

This is not true for function expressions, where the result will still be the same obtained with variables:

(function () {
alert(something);
// undefined and no errors

var something = function() {
return 123;
};
}());

Accordingly, function declaration is referenced on top of everything, variables included!
So why on bloody earth this piece of code does not pass JSLint?

var something = (function () {

// top reference available ever
// function declaration
function something() {
return oneTwoThree;
}

// second references available in this scope
// local scope variable
var oneTwoThree = 123;

// return the local function call
return something();

}());

Try by yourself the result:

Error:
Implied global: oneTwoThree 5

Unused variable: oneTwoThree 1 'something'

---------------------------------

Global something

1 'something'()
Unused oneTwoThree
Complexity 1

4 something()
Global oneTwoThree
Complexity 1

I can bet the amount of bullshit I can read in latter result is a shame for Douglas Crockford in first person, isn't it?

Not Only Inconsistencies

Another part covered by Doug speech was the with statement ... here summarize:

... somebody (n.d. I guess me) may argue that the with statement may be useful in certain situations, but since it is always ambiguous and there is nothing that could not be done without it, the with statement should disappear from JavaScript ....
... and this is what happened.
If we try "use strict"; activation in most recent browsers we can spot that the with statement is not allowed anymore, "thanks"!

A Tool To Rule Them All

It was actually a colleague of mine asking Douglas this question (or what I got about it) :

... so, you are saying that JS developers have no discipline, but don't you think that "dictating discipline" is not such easy task as well? ...
I honestly do not remember the answer but I am sure Douglas provided a proper one ... anyway ... what I do believe is that every developer has is own style, as long as syntax and readability are not too much compromised.
If we use this tool thinking our code will improve any how we are first of all acting like machines plus we are not considering a "little detail" ...

Your Team Does Not Know JavaScript

Precisely! I know this is hard to face, but in 11 years of JavaScript programming I have never found a reason to have such tool that changes allowed programming language syntax defined by specifications ... fucking read them and stop winging! (and pardon my french)
In few words, I have never had a single problem to understand any other piece of JavaScript code written by any possible developer out there but when I had a problem, and at the beginning of whatever programming language we all have, I have investigated, studied, and finally understood, what was going on in that piece of code and what was missing from my JS knowledge about it.
Surely I did not blame the other developer, since if we would like to be monkeys on daily basis, of course we should use as many tools as possible that throw warnings even if the piece of code we wrote is absolutely correct, and we still have my precedent example few paragraph before as proof ...
On the other hand, if we would like to master our JavaScript knowledge there is no way a piece of code that perfectly works could be screwed up because of JSLint.

Early JavaScript Days

When Douglas Crockford was still promoting JavaScript all over the world, nobody had any idea what he was talking about ... well, now we all have.
This bloody language is absolutely everywhere and those "feeling cool" Java developers that still think JS is a toy are regretting 50% of their studies because they just don't get it ... that's why projects like GWT exists: developers that think JavaScript is a toy, write Java that is gonna be translated into Javascript ... and this is how powerful and flexible JavaScript is.
In these days, and surely before, we truly need discipline and a lot of hints since as lazy developers we could not spend half a day reading ECMAScript 3rd Edition specs ... isn't it?
In these days, and for these developers, of course JSLint has to be there, they don't know what they are doing but hey, at least they are willing to learn something more from this tool (and most likely behind a syntax translator such GWT is, created to do not throw JSLint warnings ...) .
As demonstrated before, this is not enough.
Java skills into JavaScript language are similar to me pretendng to have Alex Martelli knowledge using Visual Basic 6 on daily basis ... I hope you know what I mean ...
As summary, if you think you can move knowledge from another programming language without deeply understanding the new one pretending you come from "something better" you are half way trough your own failure.
At the end of the day it may not matters, as long as the next point is clear for everybody.

TDD And Unit Tests Are The Only "Safer Way"

Yeah you read it right ... there is no way our JavaScript code is gonna be any safer because of JSLint or whatever JS validation tool: no fucking way!
If we think that === rather than == is all we need to be safe, without understanding why we may be safer or why we may do something simply redundant without considering cases where we want to ==, we have never been so wrong.
Unit Tests, and more Unit Tests on top of Unit Tests are the only answer to our code quality!
It does not matter how we write routines as long as real Senior Developers can understand it, simply asking more if they really don't, and as long as all our possible implementation cases have been considered.
If we are those kind of "my code pass JSLint, my code is better and safer and cleaner" develoeprs, we are simply demonstrating how much we still have to learn about programming.
I don't know any other language that religious or with need of these kind of "natural programming code evaluation tools" and we all know JavaSscript is not the first programming language ever, neither the last one.
If it's about some common code convention we don't need JSLint, we simply need a bloody wiki/web/infrastructure page able to explain it so that somebody else could eventually blame it the moment he's flexible enough to understand meant edge cases.
This is what I have answered as well during my workshop when somebody asked me what I think about JSLint, while the whole post is the reason I did not even start arguments or questions after Douglas speech, and the reason I will never do it.
We all have our style, Douglas has his own one, and I am happy for him he is that consistent.
Should I be a Douglas Crockford clone on daily basis? Hell no, since as I have said: I know WTF I am writing and why

Wednesday, May 25, 2011

JavaScript Builder from Falsy Values

Update: uglify-js as third option


Thanks to @kitgoncharov JSBuilder now includes the option to run uglify-js through Rhino ... still cross platform, a builder for any taste.




as promised during my workshop, I have created a Google Code Project with the builder used to demonstrate most advanced and common techniques to make a library, application, snippet, small and fast.

What Is JSBuilder

It's a truly simple Python module based over a certain hierarchy able to combine multiple files and produce a minified version of the application.
A similar approach has been used since ages with jQuery, and I am pretty sure there are tons of builders out there able to do similar task.
I personally created ages ago a similar project compatible with all windows platform.
However, that project was missing the possibility to put everything together, preserve some piece of code if necessary, replace some string runtime, and produce if necessary different outputs through the simplified module approach.
Here a build.py file example, the same you can find in the repository.

# JSBuilder example

# project name (from the root folder)
copyright = '(C) WebReflection JSBuilder from Falsy Values'
max_js = 'build/max.js'
min_js = 'build/min.js'

# file list (from the root/src folder)
files = [
"intro.js", #beginning of the closure
"variables.js", #local scope variables
"main.js", #some application logic
"functions.js", #functions declaration
"debug.js", #something useful or evil to debug
"outro.js" #end of the closure
]

# execute the task
import JSBuilder
JSBuilder.compile(
copyright,
max_js,
min_js,
files,
# optional list of serches
[ #mustaches in comments, hell yeah!
'/*{namespace}*/'
],
# with relative optional list of replaces
[
'var ' #produce var MyLib = ...

# it could be 'this.'
# this.MyLib = ...

# it could be 'my.personal.stuff.'
# my.personal.stuff.MyLib = ...
]
)

# let me read the result ...
import time
time.sleep(2)


Why Python

First of all the version is the 2.6 or higher but not compatible (yet) with version 3+.
Python to me is a sort of server side lingua-franca and it is missing by default only on Windows platform.
I would say the same about Java, with the slightly difference that in Python we don't need to create a class to perform a simple task as the one performed by JSBuilder.
If Python is not present in our system, we can easily find the installer in the python.org website while the build.py example code should be easy to understand even for non programmers.

Java As Well

Both YUICompressor and Google Closure Compiler come with a jar package which is a classic build out of one or more Java files. JSBuilder uses Java as well in order to call one compiler or another one with proper arguments and in a cross platform way so ... just in case you do not have Java installed, here the link to download what we need.

The Current Folder Structure

projectFolder
build
builder
src
Above structure is exactly the same you can find in the repository but don't worry, as you can spot in the build.py file we are free to change destination folders or paths without problems.
JSBuilder assumes in any case relative paths from the root of the application but if you really need a different structure feel free to replace the string '../' with the one you prefer ... it is an easily replaceable part of the script, just find and replace and that's it.

Multiple Projects

The build.py file is just an example but obviously we can create as many examples as we want, even inside the build.py file itself, changing just the part to replace, destination files, and/or copyright if necessary.
JSBuilder should be suitable for all sort of cases ... at least for all cases I have been facing since I have started with JavaScript (10 years of cases, I hope it's enough)

The Concept Behind

As you can see there are different sources behind the scene and the application is distributed across multiple files.
While this concept may be not that familiar or weird, this has been used by jQuery library since ever and even if teams may think it's not easy to maintain such distributed code, a proper structure following some standard could be more than we need to make everything simple.
As example, the file called variables.js contains all local scope variables reused inside other files as well.
Of course if a variable has a meaning for more than a file, it makes perfect sense to put it in the precedent one, even as undefined variables, to eventually assign it later.

Closure Compiler VS YUICompressor

If you checkout the whole project and you try to build once with YUI and once with Closure Compiler, simply swapping comment on line 63 of JSBuilder.py file, you will realize these minifiers are able to produce a completely different output.
I leave you read all comments inside JSBuilder.py in order to understand what happens there exactly, and I hope you will realize there is even more than zou have imagined.

Debugging Code

Sometimes you may need a portion of code for debugging purpose, and the not minified version of the file is the only place where it should be.
When it comes to debug, we would like to be able to export outside private variables or functions, still understanding their original names rather than the minified one.
The debug.js files as example is able to modify internal variables thanks to evil eval function.
This piece of code is surrounded by this comment:

//^
... the debug/evil code ...
//$

If you are familiar with regular expressions you can spot that ^ as "start evil code" and $ as "end evil code" have semantic meaning ... and this is what will never be included in the final minified version of our app.

Give It A Try

I hope those present in my Falsy Values workshops got the advantages a build system could bring on our daily basis work but I have written as many comments as possible to let you understand what is going on, how does it work, and why this simple script is freaking cool and it could potentially become our favorite build system.

What's Next

In my personal projects I have included an extra line at the end of the build.py able to create, per each build, documentation.
This kinda helps me to do not forget I have to document new or modified stuff, plus it gives me extra hints if some documentation has been lazily copied and pasted rather than being rewritten ... well, I honestly don't really like jsDocToolkit since JavaScript syntax has nothing to do with Java one but I agree is, at least, a tool flexible enough and still widely adopted and/or extended so ... if you all agree, I will put the magic documentation part there inside a build-with-doc.py file example.

Tuesday, May 24, 2011

setTimeout and setInterval with extra arguments ... once again!

Funny discussion today on twitter about "why on Earth IE still does not support extra arguments with setTimeout and setInterval" ... oh, well ...

The execScript Behaviour

Somebody in IE team thinks that the rest of the world should avoid extra arguments because of a bloody edge case as the third argument in IE is:

// ... seriously ...
setTimeout("Msgbox('WTF')", 0, "VBScript");


What IE Users Could Do

Well, rather than create a closure every bloody time we would like to reuse a function with different arguments, something posible 10 years ago via ActionScript 1, every web developer (and not only) misses the opportunity to avoid closures using a de-facto standard for some unknown reason not part yet of ECMAScript specifications.
For those interested I will show an example later, right now let's think about a solution compatible with VBScript for those mental developers, as I have been, brave enough to still use this language for some purpose.

setTimeout(function () {
// a closure for *this* edge case only
// rather than all cases "trapped" because of this!
execScript("Msgbox('WTF')", "VBScript");
}, 0);


Exactly The Same Behaviour!

Yes, if we use a string for setTimeout or setInterval this will be executed on the global scope, regardless where we defined this timer.
Accordingly, the latter example via execScript does exactly the same, since execScript executes synchronously on the global scope, and once trapped behind a timer, nothing change, same result .... happy? No, you are not!

The Classic Closure

The most common situation where we have problems is when we have a portable function defined somewhere else and we would like to use this function passing certain arguments there.

// somewhere else in the scope
function doStuff(obj) {
obj.stuffDone = true;
}


// later in our super cool application
setTimeout(
// the infamous closure
function () {
doStuff(myObj);
},
1000
);

The worst case scenario is where we would like to define timers inside a loop and unfortunately this is a truly common pattern that causes me repeated WTF tilt in my mind:

for (var i = 0; i < 10; i++) {
setTimeout(
// the double infamous closure pattern
(function(obj){
// the infamous closure
return function () {
doStuff(obj);
};
}(collection[i])),
1000
);
}


Closures And Scope Lookup Costs

Every time we access an outer scope variables we do a lookup in the ... well, outer scope. Every time we create a closure we pass through a function expression activation plus we create a nested scope that has to perform a scope lookup to access the outer function/variable.
Whenever this description makes sense or not, here the test you can try with not so powerful devices or mobile phones and tablet.
In my Atom N270 netbook that test is quite explicit: 50% less performances for each nested closure and its inline invoke.

Speed UP!!!

I have already described this pattern but I keep seeing too few developers adopting it.

for (var
createdOnce = function (obj) {
return function () {
doStuff(obj);
};
},
i = 0; i < 10; i++
) {
setTimeout(createdOnce(collection[i]), 1000);
}

Above example creates 11 functions rather than 20, which means we allocate and garbage collect loop + 1 functions rather than loop * 2.

Speed UP MORE!!!

The best part is that every browser I have tested but IE supports one or more argument with both setTimeout and setInterval.

for (var i = 0; i < 10; i++) {
setTimeout(doStuff, 1000, collection[i]);
}

How many extra/redundant/superflous closures and inline invoke we have created? 0.

How Difficult It Is

.. not at all.
It's pretty straight forward and it costs nothing for IE considering that you never bothered with this problem and you reached this point rather than skip this whole post at the beginning ... well, thanks for your attention :D , and this is your solution:

setTimeout(function (one) {
// only if not supported ...
if (!one) {
var
slice = [].slice,
// trap original versions
Timeout = setTimeout,
Interval = setInterval,
// create a delegate
delegate = function (callback, $arguments) {
$arguments = slice.call($arguments, 2);
return function () {
callback.apply(null, $arguments);
};
}
;
// redefine original versions
setTimeout = function (callback, delay) {
return Timeout(delegate(callback, arguments), delay);
};
setInterval = function (callback, delay) {
return Interval(delegate(callback, arguments), delay);
};
}
}, 0, 1);


Not Obtrusive

If we use above script at the very beginning of our web page there are extremely rare chances that the next script won't be able to use already the fixed version of setInterval and setTimeout for IE only.
If another script includes the same logic nothing will be redefined for the simple reason that variable one will be there so no double reassignment will be performed.
In the very safe scenario, considering we are inside our bigger outer scope created for our library, we can define those references as internal:

(function(){
// the beginning of our lib
var
setTimeout = window.setTimeout,
setInterval = window.setInterval
;


// the runtime check showed before ..

// .. the rest of the lib

// the end of our lib
}());

We may eventually decide to use some "isIE" check via conditional comments on our pages, since the solution costs nothing once minified, and have a normalized de-facto, fast, easier, behavior for every other browser.
Here the inline synchronous re-assignment for latter case:

(function (slice, Timeout, Interval) {
function delegate(callback, $arguments) {
$arguments = slice.call($arguments, 2);
return function () {
callback.apply(null, $arguments);
};
}
setTimeout = function (callback, delay) {
return Timeout(delegate(callback, arguments), delay);
};
setInterval = function (callback, delay) {
return Interval(delegate(callback, arguments), delay);
};
}([].slice, setTimeout, setInterval));


Update ... and As Summary

Of course the lookup is much faster than function creation, and this is the dedicated test but this post is about the summary of lookup and the classic closure creation historically used only because of this IE inconsistency.
Less lookup plus less closures around are faster, and numbers are there ( meaningful with slower devices )

Sunday, May 22, 2011

size maniacs or just twitterable examples ?

maybe both, but I like the idea!
Many times I have added something like #tweetcode at the end of a tweet created with the single goal to be small enough for ... well, a tweet!
@jedschmidt bought a spanish domain called 140byt.es based over github forks in order to provide all sort of tweets that may solve a specific problem in an efficient way: it kinda work on copy and paste!
Kinda ... because rules may not truly work stand alone and snippets are suggested without a "tooltip" example, at least in the main page.

What Can We Do In 140 Bytes ?

  • tweet a solution for a simple task
  • provide an idea about how to solve a task
  • solve a task in a truly efficient way
Yeah, some snippet is absolutely everything we may need to solve a problem.
The most simple example is the hex2rgb and rgb2hex, a problem that could be solved easily via bitwise operators and a tiny bit of math.

How Can 140 Bytes Be Enough ?

Using few tricks suggested in this page we can realize it is possible to shrink the code that badly to obtain a decent copy and paste tweet.

How Can We Contribute ?

Fork it and push it with some example. I have done the mistake posting a "117 bytes to bind" that follows jed logic but it is not forked yet.

function(a,b,c){b=[].slice.call(arguments,1);c=this;return function(){return a.apply(c,b.concat.apply(b,arguments))}}

Well, I'll do better next time while you can have fun and check examples right now ;)


Update
DAMN IT! Jed shrinked another byte!
function(a,b,c){b=[c=this].slice.call(arguments,1);return function(){return a.apply(c,b.concat.apply(b,arguments))}}