views:

65

answers:

2

Hi,

I'm trying to understand why JSLint complains about an implied global variable in the following example:

var TEST = (function () {
  var count = 0;

  function get_count() { 
    return add_one(); 
  }

  function add_one() {
    count += 1;
    return count;
  }

  return { 
    get_count: get_count
  };
}());

Running this through JSLint gives the error:

Problem at line 5 character 12: 'add_one' is not defined.

As well as saying:

Implied global: add_one 5

If you move the add_one() function before the get_count() function the error goes away. However with the code as it is above, it doesn't produce any errors when you run it in the browser. Can anyone explain why JSLint is complaining?

Thanks!
Matt

+5  A: 

This is because JSLint uses a Pratt Parser, a top-down parser, not a full-blown JavaScript interpreter. If it were truly interpreted, then it wouldn't give you that error.

add_one is an implied global because the parser didn't come across that variable yet, so it assumes that your surrounding code will have that variable. But, if you flip it around, then the parser has already came across the add_one variable and it's all peaches and cream :-)

By the way, I noticed a small typo in your closing function line: }()); should be })();.

Jacob Relkin
+1 correctomondo. JavaScript makes functions available if they are below your invoking code so long as they are not scoped, i.e. `var a = function() { }`. :)
alex
Ahhhhhh OK. Thanks Jacob, that makes total sense. Now that I understand that I can get past JSLint hurting my feelings. Thanks for correcting my code too!
m4olivei
A: 

I change the order inwhich the methods are declared it will solve your problem. As mentioned in another answer, some JavaScript parses use a top down approach to reading the code, similar to how the C programming language does it. Modern interpreters and compilers use a 2 pass approach. The first pass is reading/compiling the methods into memory. If it encounters any method calls that it does not know about it will look through the entire set of methods in memory to determine if it exists. I would recommend fixing the order because while it may not cause an issues, it will load the method into memory sooner with the change.

var TEST = (function () {
  var count = 0;

  function add_one() {
    count += 1;
    return count;
  }

  function get_count() { 
    return add_one(); 
  }

  return { 
    get_count: get_count
  };
}());
Eric