3 Replies Latest reply on Oct 16, 2010 5:17 AM by Dave Saunders

    [JS] To Read: “The Essentials of Writing High Quality JavaScript”

    [Jongware] Most Valuable Participant

      Received through The Code Project Daily News:

       

      For all just-starting Javascript writers as well as for the seasoned ones -- and the ones that think they know a trick or two : an excerpt by Stoyan Stefanov in honor of his new O'Reilly title “JavaScript Patterns”.

       

      A single page article, but it's a long page, and describes enough super-duper coding practice top tips to make your mouth water for the full deal.

       

      http://net.tutsplus.com/tutorials/javascript-ajax/the-essentials-of-writing-high-quality-j avascript/

        • 1. Re: [JS] To Read: “The Essentials of Writing High Quality JavaScript”
          Dave Saunders Level 4

          A lot of this reinforces my attitude towards scripting. I ran into a doozy last week through accidental use of a global. I had this kind of structure:

           

          1. Event handler script. This script written inside an anonymous function which I thought would protect its namespace, checks a folder for action scripts. It then loops through them running each one using what I thought of as a local variable.

           

          2. In the action script I was working on, also entirely inside an anonymous function, I had another loop where I unintentionally used a global variable with the same name (j) as the loop in the event-handler script.

           

          It turned out that in spite of the anonymous functions, the global j I used in that called action script was the same variable as the local j in the event-handler script. Apparently, the local variables at the point where a do script is executed are global variables in the script being called by the do script.

           

          Yuck! Makes me wonder if using those anonymous functions is worth the trouble.

           

          Dave

          • 2. Re: [JS] To Read: “The Essentials of Writing High Quality JavaScript”
            George_Johnson MVP & Adobe Community Professional

            Dave,

             

            That's interesting. Did you declare your j in the function with the var keyword?

            • 3. Re: [JS] To Read: “The Essentials of Writing High Quality JavaScript”
              Dave Saunders Level 4

              George,

               

              It looks like this:

               

              First Script:

               

               

              (function() {
              //snip
              for (var j = 0; supportScripts.length > j; j++) {
                   if (myTPS.timingInfo) {
                        var supportStart = new Date();
                   }
                   app.doScript(supportScripts[j]);
                   if (myTPS.timingInfo) {
                        var supportEnd = new Date();
                        myTPS.log(supportScripts[j].name + " duration: " + (supportEnd - supportStart) + " ms.", interactive);
                   }
              } // end for

               

               

              Support Script:

               

               

              (function() {
                   // include the event services object and functions
                   #include 'LC250III:ScriptSources:TPSevServe.jsx'
                   
                   // ++++++++++++++++ Main code function follows +++++++++++++++++++++++
              
                   function performFunction(aDoc, interactive, eventId, myTPS) {
                        // Here's where the actual code that does something useful goes
                        // In here, I had a loop where I used j but forgot to declare it with var
                        // Like this:
                            for (j = 0, 5 > j, j++) {
                                  // whatever
                             }
                   } // end performFunction
              
                   // ++++++++++++++++ Kick-off Code starts here +++++++++++++++++++++++++
              
                   // If the job.id scriptArg is defined, we're running under Publish
                   var interactive = !(app.scriptArgs.isDefined("job.id"));
              
                   // make our working object
                   var myTPS = new TPSevServ();
              
                   // locate the "active" document
                   if (app.scriptArgs.isDefined("job.activeDocument")) {
                        var aDoc = app.documents.item(app.scriptArgs.get("job.activeDocument"));
                   } else {
                        var aDoc = myTPS.findLiveDoc();
                        if (aDoc === null) {
                             myTPS.log("Couldn't locate active document.", interactive);
                             return;
                        }
                   }
                   var eventId = app.scriptArgs.get("job.eventId");
                   try {
                        performFunction(aDoc, interactive, eventId, myTPS);
                   } catch(e) {
                        myTPS.log("Error " + e.number + ": " + e.message + " at line: " + e.line, interactive);
                   }
              }())
              

               

               

              It turned out that by failing to declare that deeply internal loop variable as a local (I think it was even deeper than I'm showing here in that it was inside a called function), I was accidentally using the same j as in the calling script. As a result, when the calling script tried to post the duration to the log, it got an error because the value of j was wrong for picking up the supportScript's name. The error was a cryptic "[21]".

               

              At least next time I'll know what it means.

               

              But it has shaken my confidence in the value of anonymous functions. I guess the point is that names inside an anonymous function don't leak upwards into the global space, but they can flow downwards.

               

              Dave