One of the main things that really blows programmers’ minds when they really see the power of it is a topic called ‘closures’ or ‘lambda functions’ or ‘anonymous subroutines’.

I decided to edit the previous post’s code to use closures, to get the hang of this technique in JavaScript. It makes your code a lot more flexible as I think the simple example below demonstrates.

For the code, look after the jump…

<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>untitled</title>
<meta name="generator" content="TextMate http://macromates.com/">
<meta name="author" content="Steven Harms">
<!-- Date: 2006-08-19 -->
<script type="text/javascript" charset="utf-8">

    function addParagraph (manipulateText){

        var childEl = document.createElement('p');

        // This is something subtle, you need to create a text node and bond
        // that to the <p> element.  In the DOM inspector, this shows
        // up as 'nodeName' = #text
        var tf = document.createTextNode("Moopy hobo");

        // Bond the text to the <p> element
        childEl.appendChild(tf);

        // If we didn't get a closure, i think they're going to
        // do something with it in the calling section, they can have
        // the node back
        if (typeof manipulateText == 'undefined'){
            return childEl;
        }

        // But...if they sent me how to manipulate ahead of time, then
        // I'll do that

        return manipulateText(childEl);
    }

    function configurePage(doTextChange){
        //Get the HTML <body> tag reference
        var htmlParent = document.getElementsByTagName('Body')[0];

        // Create a blank <p> tag reference
        var childEl = document.createElement('p');

        //Load this up as a usable <p> element, but then do some
        // style based operations on it.  Operations are passed as
        // a closure ( i.e. a pointer to code) as the first argument

        childEl = addParagraph(
            function (node) {
                node.style.width="200px";
                node.style.fontFamily="garamond; helvetica";
                node.className='graybackground';
                node.addEventListener('mouseover',changebk,false);
                node.addEventListener('mouseout',dazzle,false);
                return node;
            }
        );

        // Handle the argument
        if ( doTextChange == 'YES' ){
            childEl.firstChild.nodeValue="Monsieur Hobo"
        }

        //Finally, put this loaded up <p> tag onto the page by appending
        //it to the <html><body> node
        htmlParent.appendChild(childEl);

    }

    // A function for callbacks, the alert() is pretty annoying when
    // testing so I've commented it out, but enabling it makes things
    // a bit more obvious
    function dazzle(){
        alert('you are dazzled');
        this.className='graybackground'
    }

    //Nifty!
    function changebk(){
        this.className='redbackground'
    }
</script>

<style type="text/css" media="screen">
    .graybackground{
        background-color: #BBB;
    }
    .redbackground{
        background-color: red;
    }
</style>

</head>
<body onload="configurePage('YES')">
<!-- Look Ma, no content! -->
</body>
</html>

Leave a Reply