Tuesday, July 24, 2012

JavaScript Closures for 6-year-olds

When I first became interested in NodeJS I decided I needed to understand closures. They're supposed to be an advanced topic in JavaScript, but they're kind of fundamental to Node's asynchronous, callback driven continuation-passing style.

My background is mainly in C/C++, so unlike Ruby programmers, who have probably been exposed to closures, I had to study up on it.

After reading some excellent technical descriptions and layman's articles, I came across a Stack Overflow post asking "How do JavaScript Closures Work?", which is really good. The writer was asking how you might explain closures to a six-year-old, because Richard Feinman said that "If you can't explain it to a six-year-old, you don't really understand it yourself".

Here's my attempt at an explanation of closures for six-year-olds:

A man goes on a long trip, leaving his home and family behind. He's very fond of his home and before he leaves he takes a picture to bring with him. On his travels he is sometimes asked to describe his home. At such times, he takes out the photograph and begins to describe it. He talks about the white picket fence, the flower boxes by the windows, and the apple trees in the back yard.

While he's away, however, his family has decided to renovate and build a 3-story condo on the spot where the house is. Gone is the white picket fence. Gone are the apple trees. Gone are the flower boxes by the windows. The entire scene has changed. Yet the travelling man knows nothing about these changes, and continues to talk about his home as he remembers it, pulling out his worn photograph to show to strangers along the way. He describes the white picket fence, the flower boxes and the trees. Unaware of the changes being made while he is away, in his mind and in his pocket he carries a picture of home that is a closure - a snapshot of the way things were - and that is all he knows.

In JavaScript, when you return a function, its like a traveling man. The function will remember the scene where it came from, just the way it was.

var color = 'white';

function leaveHome () {
   // a variable in leaveHome's scope
   var description = "My house is " + color;
   // returns another function, creating a closure over description
   return function() {
      console.log(description);
   }
}

var travellingMan = leaveHome();
travellingMan(); // "My house is white"
color = 'red';   // They painted the house
travellingMan(); // "My house is white"

A couple points to notice: 
  1. In JavaScript, functions are objects, too. Functions can create and return other functions.
  2. When you return a function or pass one as an argument, it doesn't need a name. It can be defined right in-line as an anonymous object.
  3. When the return function is created it "closes over" the variables in it's scope. In the example it takes a snapshot of the description variable.

Friday, July 20, 2012

Thursday, July 19, 2012

JSLint in Sublime Text 2

TLDR; Easy JSLint in Sublime Text 2, featuring auto-lint on save, jump to errors, menu shortcuts and preferences. Download it from github.

I've been using Sublime Text 2 as my go-to editor for JavaScript, and set up a custom build system in Sublime Text 2 to run JSLint and report errors automatically when saving a .js, .json, or .html file.

This has been working great. Whenever I save a file, it tells me immediately if there are any problems.  Since I already have the file open with my recent changes, I can easily fix things up and re-save. There's no waiting for some monolithic build process to generate a report, which I may or may not pay attention to, or context switching between tools and screens to find the source of the problem. I set several options so it won't complain about typical NodeJS styles, and I make sure I get the "OK" when I save things. It keeps things very simple and as a result my code is all fully JSLint-ed.

If you have node installed, then all you need to do is install this package in Sublime Text.  The install guide is on GitHub here:

https://github.com/darrenderidder/Sublime-JSLint

Update (22/01/2013): This package used to require the node-jslint module, but this didn't work well for Windows users. So I've added jslint directly into the package, and now the only dependency is to have node installed.

Update (13/05/2013): Jan Raasch added a bunch of cool features, like being able to lint an entire directory, and made some of the preferences easier to configure.

Wednesday, July 11, 2012

Selenium IDE Sideflow Update 2

I've updated the Sideflow (Selenium IDE Flowcontrol) plugin. You can download the latest version here: https://github.com/73rhodes/sideflow

The "gotolabel" command is renamed with camel-casing as "gotoLabel", so you may need to update your old Selenium tests if they use the old "gotolabel". Note that "goto" is a synonym for "gotoLabel", so if you wrote your tests using "goto" they should just keep working.

While I really appreciate contributions and suggestions, I've decided to remove the recent forEach additions. There were a few reasons for this.
  1. foreach functionality can be done with the existing while / endWhile commands.
  2. The implementation of foreach didn't actually provide a foreach command.
  3. Users reported errors in the new feature. Given (1) and (2) I wasn't really interested in debugging it.

To provide a simple way for users to build a collection, I added the "push" command. In Selenese, "push" works like you'd expect in JavaScript, except it will automatically create the array for you if it doesn't already exist.

So, to build up a collection, you can do this:

getEval | delete storedVars['mycollection']
push    | {name: 'darren', status: 'groovy'} | mycollection
push    | {name: 'basil', status: 'happy'}   | mycollection

Note the use of 'getEval' to clear the collection first. Unlike 'runScript', 'getEval' runs in the context of the Selenium object, allowing us to modify storedVars.

To do something with every item in the collection (like foreach), you can do this:

storeEval | storedVars['mycollection'].length | x
echo      | mycollection has ${x} items
while     | storedVars['x'] > 0
storeEval | storedVars.mycollection[${x}-1]   | temp
echo      | ${temp}
storeEval | ${x}-1                            | x
endWhile

Translate