Why should I care about functions as first-class citizens?

Feb 5, 2010   //   by Noah Heldman   //   Blog  //  No Comments

The term “first-class citizen” as it applies to a feature of a programming language has always sounded weird to me. Besides anthropomorphizing code, it’s vaguely insulting, as if other language features might be considered “illegal immigrants”. On top of that, I’ve been using functions as first-class citizens in JavaScript for a long time now, but never appreciated why being first class was so special.

Well, I found a situation that changed my mind.

I needed to override the default behavior of FCKEditor (or CKEditor, as it’s now known), but I realized that the platform I was working with was already overriding FCKEditor. Did I panic? Well, yes. But, should I have? No! Here’s why:

  1: // Override FCKEditor function that runs when editor finishes loading
  2: function FCKeditor_OnComplete(editor)
  3: {
  4:   // Grab the original function that is called when the editor's
  5:   // Save button is clicked.
  6:   // Hey, is that var holding a first class citizen?
  7:   var origSaveFunction = editor.Commands.GetCommand('Save').Execute;
  8:
  9:   // Override the original function
 10:   editor.Commands.GetCommand('Save').Execute = function() {
 11:
 12:     // ADD YOUR OWN LOGIC HERE!
 13:
 14:     // Execute the original save function so we don't lose any of
 15:     // the original framework's behavior
 16:     // Wait, you just called my variable with parens, and it executed
 17:     // my function? Now that's first class!
 18:     origSaveFunction();
 19:
 20:     // ADD YOUR OWN LOGIC HERE TOO!
 21:   };
 22: }

Okay, so what’s the big deal? The cool thing here is that I can grab any function that I have access to, store it in a variable, then assign my own function to the original command. So far, so good. But, the real power is in line 18, where you can recreate all of the original behavior by calling the function you stored in a variable.

You could even extend this idea to write an AOP framework in JavaScript, that injects, for example, logging behavior before and after each function call. But before I go down that road, I think I’ll let the beauty of this sink in for a while.

Totes magotes.

Leave a comment

(will not be published)

Recent Posts