Loading ...
Sorry, an error occurred while loading the content.

Implied global or hoisted var

Expand Messages
  • Bert Belder
    When linting this code: (function outer() { var foo = function() { bar(); }; var bar = function() { }; foo(); })(); JSLint gives me these warnings: Problem at
    Message 1 of 10 , Jul 27, 2010
    • 0 Attachment
      When linting this code:

      (function outer() {
      var foo = function() {
      bar();
      };

      var bar = function() {
      };

      foo();
      })();

      JSLint gives me these warnings:

      Problem at line 3 character 5: 'bar' is not defined.
      Implied global: bar 3
      Unused variable: bar 1 outer

      I think all three warnings are wrong. Due to type hoisting the 'var bar'
      declaration applies to the entire scope of the 'outer' function, so foo()
      inherits 'bar' from 'outer'.

      Or am I missing something here?

      best regards,
      Bert
    • Mark Volkmann
      JSLint wants you to define functions before their first call is encountered. While your code would work the way you haven t, it s considered better style to
      Message 2 of 10 , Jul 27, 2010
      • 0 Attachment
        JSLint wants you to define functions before their first call is encountered.
        While your code would work the way you haven't, it's considered better style
        to change the order of your code.

        On Tue, Jul 27, 2010 at 4:52 PM, Bert Belder <bertbelder@...> wrote:

        >
        >
        > When linting this code:
        >
        > (function outer() {
        > var foo = function() {
        > bar();
        > };
        >
        > var bar = function() {
        > };
        >
        > foo();
        > })();
        >
        > JSLint gives me these warnings:
        >
        > Problem at line 3 character 5: 'bar' is not defined.
        > Implied global: bar 3
        > Unused variable: bar 1 outer
        >
        > I think all three warnings are wrong. Due to type hoisting the 'var bar'
        > declaration applies to the entire scope of the 'outer' function, so foo()
        > inherits 'bar' from 'outer'.
        >
        > Or am I missing something here?
        >
        > best regards,
        > Bert
        >
        >
        >



        --
        R. Mark Volkmann
        Object Computing, Inc.


        [Non-text portions of this message have been removed]
      • bertbelder
        Allright. But what if I have two functions that mutually call each other (that was when I ran into this)? Then there is always one that is encountered before
        Message 3 of 10 , Jul 27, 2010
        • 0 Attachment
          Allright. But what if I have two functions that mutually call each other (that was when I ran into this)? Then there is always one that is 'encountered' before it is defined.

          Furthermore, IMHO if JSLint isn't happy with a certain coding style, that's what it should complain about -- instead of producing wrong statements about the code.

          --- In jslint_com@yahoogroups.com, Mark Volkmann <r.mark.volkmann@...> wrote:
          >
          > JSLint wants you to define functions before their first call is encountered.
          > While your code would work the way you haven't, it's considered better style
          > to change the order of your code.
          >
          > On Tue, Jul 27, 2010 at 4:52 PM, Bert Belder <bertbelder@...> wrote:
          >
          > >
          > >
          > > When linting this code:
          > >
          > > (function outer() {
          > > var foo = function() {
          > > bar();
          > > };
          > >
          > > var bar = function() {
          > > };
          > >
          > > foo();
          > > })();
          > >
          > > JSLint gives me these warnings:
          > >
          > > Problem at line 3 character 5: 'bar' is not defined.
          > > Implied global: bar 3
          > > Unused variable: bar 1 outer
          > >
          > > I think all three warnings are wrong. Due to type hoisting the 'var bar'
          > > declaration applies to the entire scope of the 'outer' function, so foo()
          > > inherits 'bar' from 'outer'.
          > >
          > > Or am I missing something here?
          > >
          > > best regards,
          > > Bert
          > >
          > >
          > >
          >
          >
          >
          > --
          > R. Mark Volkmann
          > Object Computing, Inc.
          >
          >
          > [Non-text portions of this message have been removed]
          >
        • Marcel Duran
          You could use: var foo, bar; foo = function () { bar(); }; bar = function () { foo(); }; Marcel ... -- Marcel Duran [Non-text portions of this message have
          Message 4 of 10 , Jul 27, 2010
          • 0 Attachment
            You could use:

            var foo, bar;

            foo = function () {
            bar();
            };

            bar = function () {
            foo();
            };

            Marcel

            On Tue, Jul 27, 2010 at 5:52 PM, bertbelder <bertbelder@...> wrote:

            >
            >
            >
            >
            > Allright. But what if I have two functions that mutually call each other
            > (that was when I ran into this)? Then there is always one that is
            > 'encountered' before it is defined.
            >
            > Furthermore, IMHO if JSLint isn't happy with a certain coding style, that's
            > what it should complain about -- instead of producing wrong statements about
            > the code.
            >
            >
            > --- In jslint_com@yahoogroups.com <jslint_com%40yahoogroups.com>, Mark
            > Volkmann <r.mark.volkmann@...> wrote:
            > >
            > > JSLint wants you to define functions before their first call is
            > encountered.
            > > While your code would work the way you haven't, it's considered better
            > style
            > > to change the order of your code.
            > >
            > > On Tue, Jul 27, 2010 at 4:52 PM, Bert Belder <bertbelder@...> wrote:
            > >
            > > >
            > > >
            > > > When linting this code:
            > > >
            > > > (function outer() {
            > > > var foo = function() {
            > > > bar();
            > > > };
            > > >
            > > > var bar = function() {
            > > > };
            > > >
            > > > foo();
            > > > })();
            > > >
            > > > JSLint gives me these warnings:
            > > >
            > > > Problem at line 3 character 5: 'bar' is not defined.
            > > > Implied global: bar 3
            > > > Unused variable: bar 1 outer
            > > >
            > > > I think all three warnings are wrong. Due to type hoisting the 'var
            > bar'
            > > > declaration applies to the entire scope of the 'outer' function, so
            > foo()
            > > > inherits 'bar' from 'outer'.
            > > >
            > > > Or am I missing something here?
            > > >
            > > > best regards,
            > > > Bert
            > > >
            > > >
            > > >
            > >
            > >
            > >
            > > --
            > > R. Mark Volkmann
            > > Object Computing, Inc.
            > >
            > >
            > > [Non-text portions of this message have been removed]
            > >
            >
            >
            >



            --
            Marcel Duran


            [Non-text portions of this message have been removed]
          • Cheney, Edward A SSG RES USAR USARC
            These suggestions are all wrong. The problem here is when a variable invoked and defined. You can use: function foo () { bar(); } function bar () { var a =
            Message 5 of 10 , Jul 27, 2010
            • 0 Attachment
              These suggestions are all wrong.

              The problem here is when a variable invoked and defined.

              You can use:

              function foo () {
              bar();
              }

              function bar () {
              var a = "1234";
              }

              In the previous example you will notice that function bar does not directly point to a call to function foo, because function foo directly calls to function bar. If function bar did directly have a call to function foo there would be an endless recursion.

              You will also notice that the functions are invoked using the "function" keyword directly and not with the "var" keyword. Invoking functions with the "function" moves the function to the top of the stack of the current parent so that function calls can exist at any place in the given scope.

              Functions invoked with the var command are treated just like every other variable. This means it must be declared before it is used or it will be both undefined and an implied global. This means the JSLint error output is not being a pain in the ass, but is reporting a valid error.

              Austin Cheney
              http://prettydiff.com/
            • Mark Volkmann
              Edward, Starting your reply with These suggestions are all wrong. is rude, especially when they are not. Here is the original code, modified so JSLint likes
              Message 6 of 10 , Jul 28, 2010
              • 0 Attachment
                Edward,

                Starting your reply with "These suggestions are all wrong." is rude,
                especially when they are not.

                Here is the original code, modified so JSLint likes as much of it as
                possible and including a couple of print statements so we can see if it
                works.

                (function outer() {
                var foo = function () {
                print('in foo');
                bar();
                };

                var bar = function () {
                print('in bar');
                };

                foo();
                }());

                JSLint has two complaints about this code.
                1) at line 4, 'bar' is not defined.
                2) at line 7, Too many var statements.

                Complaint #1 is eliminated by simply reversing the order of the function
                declarations.
                Marcel's suggestion to declare foo and bar before they are defined
                eliminates both issues in one shot.

                Also, you said JSLint is reporting a valid error, but the code runs just
                fine ... at least in Rhino.

                On Tue, Jul 27, 2010 at 10:40 PM, Cheney, Edward A SSG RES USAR USARC <
                austin.cheney@...> wrote:

                >
                >
                > These suggestions are all wrong.
                >
                > The problem here is when a variable invoked and defined.
                >
                > You can use:
                >
                > function foo () {
                > bar();
                > }
                >
                > function bar () {
                > var a = "1234";
                > }
                >
                > In the previous example you will notice that function bar does not directly
                > point to a call to function foo, because function foo directly calls to
                > function bar. If function bar did directly have a call to function foo there
                > would be an endless recursion.
                >
                > You will also notice that the functions are invoked using the "function"
                > keyword directly and not with the "var" keyword. Invoking functions with the
                > "function" moves the function to the top of the stack of the current parent
                > so that function calls can exist at any place in the given scope.
                >
                > Functions invoked with the var command are treated just like every other
                > variable. This means it must be declared before it is used or it will be
                > both undefined and an implied global. This means the JSLint error output is
                > not being a pain in the ass, but is reporting a valid error.
                >
                > Austin Cheney
                > http://prettydiff.com/
                >
                >



                --
                R. Mark Volkmann
                Object Computing, Inc.


                [Non-text portions of this message have been removed]
              • bertbelder
                I know that reversing the declaration order would fix the example code I posted. However the situation that caused to me run into this doesn t really allow
                Message 7 of 10 , Jul 28, 2010
                • 0 Attachment
                  I know that reversing the declaration order would fix the example code I posted. However the situation that caused to me run into this doesn't really allow reversing declaration orders without making the code really unreadable. Let me explain.

                  Suppose you have to load several pieces of data *asynchronously* (using ajax for example) where the next data source to be loaded depends on data loaded before. Let's say the function `ajax(url, callback)` is defined, that does an ajax request and calls the callback when the response arrives.
                  Then you could write:

                  var whatWereLookingFor;
                  ajax('/some/url', function(result) {
                  ...
                  ajax('/some/other/' + result.x, function(result) {
                  ...
                  ajax('/xyz/' + result.bar, function(result) {
                  ...
                  ajax('/bar/' + result.id, function(result) {
                  // Woohoo we got it
                  whatWereLookingFor = result;
                  });
                  });
                  });
                  });

                  But that's terribly readable. So I was trying to write:

                  function loadSome() {
                  ajax("/some/url", loadOther);
                  }
                  function loadOther(result) {
                  ajax("/some/other/" + result.x, loadFoo);
                  }
                  function loadFoo(result) {
                  ajax("/xyz/" + result.bar, loadBar);
                  }
                  function loadBar(result) {
                  ...
                  }

                  But JSLint doesn't eat that.

                  The suggestion to reverse declaration order would solve the JSLint error, but then the function that is called last would be defined first, which I think would make the code confusing to a reader.

                  The other solution would be to put a statement like
                  var loadSome, loadOther, loadFoo, loadBar at the start of the function but that clutters my code with unnecessary statements, besides requiring me to keep the var statement in sync with the functions actually defined.

                  So, any suggestions here?

                  I don't really mind that JSLint complains when encountering a function call before the function is defined. But I would be very happy if it would just say that, and not mess up the implied globals list with variables that are NOT global.

                  - Bert
                • Michael
                  ... Bert; You re making a bunch of assumptions about your code. In the future you might try to make some changes that will make your code wrong. Imagine in
                  Message 8 of 10 , Jul 28, 2010
                  • 0 Attachment
                    On Wed, Jul 28, 2010 at 8:44 AM, bertbelder <bertbelder@...> wrote:

                    >
                    >
                    > I know that reversing the declaration order would fix the example code I
                    > posted. However the situation that caused to me run into this doesn't really
                    > allow reversing declaration orders without making the code really
                    > unreadable. Let me explain.
                    >
                    > Suppose you have to load several pieces of data *asynchronously* (using
                    > ajax for example) where the next data source to be loaded depends on data
                    > loaded before. Let's say the function `ajax(url, callback)` is defined, that
                    > does an ajax request and calls the callback when the response arrives.
                    > Then you could write:
                    >
                    > var whatWereLookingFor;
                    > ajax('/some/url', function(result) {
                    > ...
                    > ajax('/some/other/' + result.x, function(result) {
                    > ...
                    > ajax('/xyz/' + result.bar, function(result) {
                    > ...
                    > ajax('/bar/' + result.id, function(result) {
                    > // Woohoo we got it
                    > whatWereLookingFor = result;
                    > });
                    > });
                    > });
                    > });
                    >
                    > But that's terribly readable. So I was trying to write:
                    >
                    > function loadSome() {
                    > ajax("/some/url", loadOther);
                    > }
                    > function loadOther(result) {
                    > ajax("/some/other/" + result.x, loadFoo);
                    > }
                    > function loadFoo(result) {
                    > ajax("/xyz/" + result.bar, loadBar);
                    > }
                    > function loadBar(result) {
                    > ...
                    > }
                    >
                    > But JSLint doesn't eat that.
                    >
                    > The suggestion to reverse declaration order would solve the JSLint error,
                    > but then the function that is called last would be defined first, which I
                    > think would make the code confusing to a reader.
                    >
                    > The other solution would be to put a statement like
                    > var loadSome, loadOther, loadFoo, loadBar at the start of the function but
                    > that clutters my code with unnecessary statements, besides requiring me to
                    > keep the var statement in sync with the functions actually defined.
                    >
                    > So, any suggestions here?
                    >
                    > I don't really mind that JSLint complains when encountering a function call
                    > before the function is defined. But I would be very happy if it would just
                    > say that, and not mess up the implied globals list with variables that are
                    > NOT global.
                    >
                    > - Bert
                    >
                    Bert;

                    You're making a bunch of assumptions about your code. In the future you
                    might try to make some changes that will make your code wrong. Imagine in
                    your example:

                    (function outer() {
                    var foo = function() {
                    bar();
                    };

                    if (true) {
                    return;
                    }

                    var bar = function() {
                    };

                    foo();
                    })();

                    Suddenly your variable does become global. JSLint recommends you define all
                    your variables at the top of each scope, so this kind of thing won't happen.
                    JSLint will hurt your feelings, but it makes your code better.


                    [Non-text portions of this message have been removed]
                  • bertbelder
                    ... Erm, I don t see it. What becomes global then?
                    Message 9 of 10 , Jul 28, 2010
                    • 0 Attachment
                      > You're making a bunch of assumptions about your code. In the future you
                      > might try to make some changes that will make your code wrong. Imagine in
                      > your example:
                      >
                      > (function outer() {
                      > var foo = function() {
                      > bar();
                      > };
                      >
                      > if (true) {
                      > return;
                      > }
                      >
                      > var bar = function() {
                      > };
                      >
                      > foo();
                      > })();
                      >
                      > Suddenly your variable does become global. JSLint recommends you define all
                      > your variables at the top of each scope, so this kind of thing won't happen.

                      Erm, I don't see it. What becomes global then?
                    • Michael
                      ... beyond confusing if you have it also defined in the global scope. [Non-text portions of this message have been removed]
                      Message 10 of 10 , Jul 28, 2010
                      • 0 Attachment
                        On Wed, Jul 28, 2010 at 9:07 AM, bertbelder <bertbelder@...> wrote:

                        >
                        >
                        > > You're making a bunch of assumptions about your code. In the future you
                        > > might try to make some changes that will make your code wrong. Imagine in
                        > > your example:
                        > >
                        > > (function outer() {
                        > > var foo = function() {
                        > > bar();
                        > > };
                        > >
                        > > if (true) {
                        > > return;
                        > > }
                        > >
                        > > var bar = function() {
                        > > };
                        > >
                        > > foo();
                        > > })();
                        > >
                        > > Suddenly your variable does become global. JSLint recommends you define
                        > all
                        > > your variables at the top of each scope, so this kind of thing won't
                        > happen.
                        >
                        > Erm, I don't see it. What becomes global then?
                        >
                        > You're right, I need more coffee. It becomes undefined due to hoisting, but
                        beyond confusing if you have it also defined in the global scope.


                        [Non-text portions of this message have been removed]
                      Your message has been successfully submitted and would be delivered to recipients shortly.