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.



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



            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



              It looks like this:


              First Script:



              (function() {
              for (var j = 0; supportScripts.length > j; j++) {
                   if (myTPS.timingInfo) {
                        var supportStart = new Date();
                   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);
                   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.