raganwald
(This is a snapshot of my old weblog. New posts and selected republished essays can be found at raganwald.com.)

Monday, May 15, 2006
  JavaScript Pop Quiz Remarks


Here's an email I sent in response to a colleague's question about some sample JavaScript. If you haven't already seen it, you might want to look at the code first.

Joe:

You seem to understand the behaviour perfectly. The problem was that we wanted to call set_datetime(...) with a different value for each cell in the table. We know the values when we build the table cell by cell.

However, if we write the code as:

    thisCell.onclick =
function() { set_datetime( dt_current_day.valueOf(), true);

At run time each cell will have a function that gets the value of dt_current_day when the cell is clicked, not when the code was written into the cell. I think we end up with the last day in the calendar. We want to capture the value when of dt_current_day when we build the function, not later when the function is called.

The code given makes an anonymous function (let's call it the "outer function") and calls it immediately. That call copies dt_current_day.valueOf() into the day variable and returns a function (the "inner function") that uses the day variable. The inner function is the one assigned to the cell's onclick handler.

The reason it works is that every time you call the outer function you manufacture a new day variable. If you did the assignment without calling a function, like this:

    var day = dt_current_day.valueOf();
thisCell.onclick =
function() { set_datetime( day, true);

...you would end up with the wrong behaviour because all of the onclick handlers would share the same day variable.

This pattern is so common that Lisp-like languages (including Scheme) have a family of macros called let to do this for us. In Scheme, our code would look something like this:

    (let (
(day (value-of dt_current_day)))
(!set (handler thisCell 'onclick)
(lambda () (set-datetime! day #t))))

Although using let looks just like a straightforward assignment using set!, it actually creates a new variable every time. It should not surprise you to learn (if you didn't already know) that behind the scenes let is a macro that rewrites the code into an anonymous outer function just like the JavaScript sample.

p.s. This problem can be solved in other ways. The original code actually wrote the onclick handler out as an href in plain text. It copied the value of dt_current_date out as a string. Essentially, it was doing "code generation." Also, it would be possible to create an object with a field to store the date. You'd have to do that in a language like Java where functions don't really exist independently of objects and classes.

p.p.s. I can't believe I managed to explain the whole thing without resorting to the c-word!
 

Comments on “JavaScript Pop Quiz Remarks:




<< Home
Reg Braithwaite


Recent Writing
Homoiconic Technical Writing / raganwald.posterous.com

Books
What I‘ve Learned From Failure / Kestrels, Quirky Birds, and Hopeless Egocentricity

Share
rewrite_rails / andand / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

Beauty
IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

Work
The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Management
Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

Notation
The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Opinion
Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

Whimsey
The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

History
06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /