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

Re: [jslint] && as flow control

Expand Messages
  • Michael Lorton
    I don t know why you have a smiley at the end there. new Boolean(false) (and new String()) being truthy is a Bad Part. Perhaps :-( is too severe but anything
    Message 1 of 12 , Mar 12, 2010
    View Source
    • 0 Attachment
      I don't know why you have a smiley at the end there. new Boolean(false) (and new String()) being truthy is a Bad Part.

      Perhaps :-( is too severe but anything more cheerful than :-| is just perverse.

      M.





      ________________________________
      From: Stefan Weiss <weiss@...>
      To: jslint_com@yahoogroups.com
      Sent: Fri, March 12, 2010 3:18:52 PM
      Subject: Re: [jslint] && as flow control

      Michael Lorton wrote:
      > Now, can someone explain to me why an empty list is truthy. Is that just
      > a bug?

      What's an empty list? Did you mean an empty Array? Arrays are objects,
      and all objects are "truthy". Even 'new Boolean(false)' :-)


      stefan


      ------------------------------------

      Yahoo! Groups Links



      [Non-text portions of this message have been removed]
    • Michael Mikowski
      If you use jslint and have read the good parts, you certainly should be aware of type coercion. Using && and || for flow control doesn t require coercion
      Message 2 of 12 , Mar 12, 2010
      View Source
      • 0 Attachment
        If you use jslint and have read "the good parts," you certainly should be aware of type coercion. Using && and || for flow control doesn't require coercion but it certainly encourages it. Writing this:

        ary[0] && obj['key'] && bar && alert('guantlet passed');

        gives us 3 type coercions, roughly equivalent to:

        ( ary[0] == true ) && ( obj['key'] == true ) && ( bar == true ) && alert('gauntlet passed');

        As for "(maybe, unless it is autovivified)," how many people need to look that up? Because js does "pretend" keys exist when looking up an array or object value. To wit:

        // false if ary[0] does not exist OR if it does exist and the value is not "truthy"
        ary[0] ....

        // true only if array has element 0
        ary.hasOwnProperty(0) ...

        And before anyone asks, the latest version of firebug (1.5.2) with STRICT warnings doesn't show a thing if you address uninitialized ary[x] where x can be any numerical value (it does catch object keys, however).

        The Good Parts doesn't go into depth about it, but on page 120 when explaining jslint, it states: "An expression statement is expected to be an assignment, a function/method call, or delete. All other expression statements are considered errors." Type coercion errors are discussed on page 121.


        In the end, using expression statements can give you all the terseness of a regular expression without the precision and power. It can be the worst of both worlds. They don't pass our code reviews.




        ________________________________
        From: Stefan Weiss <weiss@...>
        To: jslint_com@yahoogroups.com
        Sent: Fri, March 12, 2010 2:09:38 PM
        Subject: Re: [jslint] && as flow control


        Michael Mikowski wrote:
        > Probably because type coercion is considered sloppy programming in any
        > language. In this case, foo[0] test for "truthiness" which means the
        > value must be /true/, or non-zero, or a non-empty string, or defined
        > (maybe, unless it is autovivified) , or ... and the list goes on.

        There's no Autovivification in JS, maybe you were thinking of Perl.
        Anyway, type coercion can't be the reason for the JSLint error, or this
        construct would pass:

        typeof foo[0] == "undefined" && fop = foo.shift();

        Type coercion can happen with or without this use of '&&' for flow
        control, same as with the more usual if/else. I rather suspect there are
        two other problems with this statement. The first is the assignment: if
        you wrap it in parentheses, JSLint will parse it correctly and issue a
        different warning:

        foo[0] && (fop = foo.shift()) ;

        "Expected an assignment or function call and instead saw an expression."

        Expression statements are valid in ECMAScript, but they aren't part of
        DC's Good Parts. I don't have the book at home, so I can't look up the
        rationale for that right now; maybe someone else can.

        > Can you name all "truthy" or "falsy" conditions off the top of your
        > head? How many on your team can?

        It's impossible to name all truthy values, but the falsy ones should be
        known to every JS developer. There aren't that many: null, undefined, 0,
        false, '', and NaN.

        I agree that it's harder to remember all the different rules for type
        coercion. For example:

        var x = new String("");

        // this prints "true"
        if (x) { console.log( "true"); }

        // and so does this, go figure...
        if (x == false) { console.log( "true"); }

        There are many other confusing examples like this.

        stefan



        [Non-text portions of this message have been removed]
      • Stefan Weiss
        ... And the exact same thing happens if you don t use expression statements: if (ary[0] && obj[ key ] && bar) { alert( guantlet passed ); } Expression
        Message 3 of 12 , Mar 12, 2010
        View Source
        • 0 Attachment
          Michael Mikowski wrote:
          > Using && and || for flow control doesn't
          > require coercion but it certainly encourages it. Writing this:
          >
          > ary[0] && obj['key'] && bar && alert('guantlet passed');
          >
          > gives us 3 type coercions, roughly equivalent to:
          >
          > ( ary[0] == true ) && ( obj['key'] == true ) && ( bar == true ) &&
          > alert('gauntlet passed');

          And the exact same thing happens if you don't use expression statements:

          if (ary[0] && obj['key'] && bar) {
          alert('guantlet passed');
          }

          Expression statements and type coercion are not directly related; it's
          the "&&" operator which forces boolean context. If you don't want the
          value of "ary[0]" or "bar" or whatever evaluated in boolean context,
          then don't use "&&", or do an explicit comparison with the correct type.

          In many situations, like when the possible contents of "ary" are known,
          or when all falsy values are to be excluded, it's more concise to use
          "&&". Nothing wrong with that, if you know what you're doing - there are
          tens of valid examples in the JSLint source itself.

          > As for "(maybe, unless it is autovivified)," how many people need to
          > look that up? Because js does "pretend" keys exist when looking up an
          > array or object value. To wit:
          >
          > // false if ary[0] does not exist OR if it does exist and the value is
          > not "truthy"
          > ary[0] ....
          >
          > // true only if array has element 0
          > ary.hasOwnProperty(0) ...
          >
          > And before anyone asks, the latest version of firebug (1.5.2) with
          > STRICT warnings doesn't show a thing if you address uninitialized ary[x]
          > where x can be any numerical value (it does catch object keys, however).

          That doesn't prove that ary[0] is autovivified, only that Mozilla
          decided not to issue a strict warning when a nonexistent array index is
          accessed. If there was any autovivification, the property "0" would
          exist after an attempt to read it. This is not the case:

          var ary = [];
          console.log(ary[0]); // "undefined"
          for (var prop in ary) { console.log(prop); } // nothing

          (Aside, I think the "strict" warnings in Firefox are way over the top. I
          don't know any other developer who pays attention to them. Even the
          JSLint script triggers numerous warnings.)

          > The Good Parts doesn't go into depth about it, but on page 120 when
          > explaining jslint, it states: "An expression statement is expected to be
          > an assignment, a function/method call, or delete. All other expression
          > statements are considered errors."

          Thanks for checking.
          I guess the OP was hoping for more of an explanation.

          By the way, I can think of a couple more expression statements that are
          accepted by JSLint: pre/postfix increment and decrement, bit shifting,
          and '"use strict";' (the former two are not part of the Good Parts, and
          there are options to disallow them).

          > In the end, using expression statements can give you all the terseness
          > of a regular expression without the precision and power. It can be the
          > worst of both worlds. They don't pass our code reviews.

          I don't understand the comparison with regular expressions. Anyway, I'm
          not in any way advocating the use of these "flow control" expression
          statements. I happen to like them (but then, I also like Perl), others
          don't, no big deal. They are easy enough to avoid when I'm writing
          JSLint compatible scripts.


          stefan
        • Michael Mikowski
          From: Stefan Weiss To: jslint_com@yahoogroups.com Sent: Fri, March 12, 2010 6:08:23 PM Subject: Re: [jslint] && as flow control ... I think we
          Message 4 of 12 , Mar 12, 2010
          View Source
          • 0 Attachment
            From: Stefan Weiss <weiss@...>
            To: jslint_com@yahoogroups.com
            Sent: Fri, March 12, 2010 6:08:23 PM
            Subject: Re: [jslint] && as flow control

            > Expression statements and type coercion are not directly related; it's
            > the "&&" operator which forces boolean context. If you don't want the
            > value of "ary[0]" or "bar" or whatever evaluated in boolean context,
            > then don't use "&&", or do an explicit comparison with the correct type.

            I think we agree. This is our example, but written for better precision:

            if ( arg.hasOwnProperty(0) && obj.hasOwnProperty(0) && bar === true ){...}

            > That doesn't prove that ary[0] is autovivified, only that Mozilla
            > decided not to issue a strict warning when a nonexistent array index is
            > accessed. If there was any autovivification, the property "0" would
            > exist after an attempt to read it. This is not the case.

            True, js does not autovivify. But during comparisons it acts like it does.
            So if one is using "if (ary[x])" to test if an element exists, they are
            in for an unpleasant surprise when it comes time to debug.

            I wasn't advocating the idea of using strict warnings either, just illustrating
            that even with the strictest warnings there is no way to tell if an array value
            is uninitialized unless you directly check for it.

            > I don't understand the comparison with regular expressions.

            Don't get me wrong - I love regular expressions and use them all the time.
            They can be very precise and powerful. It is their terseness that scares
            a lot of people, and makes them hard to debug sometimes.
            Flow controls like 'ary[0] && obj['key'] && bar && ...'
            are also terse, but lack precision, so they can be even more difficult to debug.

            > Anyway, I'm
            > not in any way advocating the use of these "flow control" expression
            > statements. I happen to like them (but then, I also like Perl), others
            > don't, no big deal. They are easy enough to avoid when I'm writing
            > JSLint compatible scripts.

            Never say never; everything has its place :) Oh, and I'm a big fan of
            Perl too :)




            ________________________________
            From: Stefan Weiss <weiss@...>
            To: jslint_com@yahoogroups.com
            Sent: Fri, March 12, 2010 6:08:23 PM
            Subject: Re: [jslint] && as flow control


            Michael Mikowski wrote:
            > Using && and || for flow control doesn't
            > require coercion but it certainly encourages it. Writing this:
            >
            > ary[0] && obj['key'] && bar && alert('guantlet passed');
            >
            > gives us 3 type coercions, roughly equivalent to:
            >
            > ( ary[0] == true ) && ( obj['key'] == true ) && ( bar == true ) &&
            > alert('gauntlet passed');

            And the exact same thing happens if you don't use expression statements:

            if (ary[0] && obj['key'] && bar) {
            alert('guantlet passed');
            }

            Expression statements and type coercion are not directly related; it's
            the "&&" operator which forces boolean context. If you don't want the
            value of "ary[0]" or "bar" or whatever evaluated in boolean context,
            then don't use "&&", or do an explicit comparison with the correct type.

            In many situations, like when the possible contents of "ary" are known,
            or when all falsy values are to be excluded, it's more concise to use
            "&&". Nothing wrong with that, if you know what you're doing - there are
            tens of valid examples in the JSLint source itself.

            > As for "(maybe, unless it is autovivified) ," how many people need to
            > look that up? Because js does "pretend" keys exist when looking up an
            > array or object value. To wit:
            >
            > // false if ary[0] does not exist OR if it does exist and the value is
            > not "truthy"
            > ary[0] ....
            >
            > // true only if array has element 0
            > ary.hasOwnProperty( 0) ...
            >
            > And before anyone asks, the latest version of firebug (1.5.2) with
            > STRICT warnings doesn't show a thing if you address uninitialized ary[x]
            > where x can be any numerical value (it does catch object keys, however).

            That doesn't prove that ary[0] is autovivified, only that Mozilla
            decided not to issue a strict warning when a nonexistent array index is
            accessed. If there was any autovivification, the property "0" would
            exist after an attempt to read it. This is not the case:

            var ary = [];
            console.log( ary[0]); // "undefined"
            for (var prop in ary) { console.log( prop); } // nothing

            (Aside, I think the "strict" warnings in Firefox are way over the top. I
            don't know any other developer who pays attention to them. Even the
            JSLint script triggers numerous warnings.)

            > The Good Parts doesn't go into depth about it, but on page 120 when
            > explaining jslint, it states: "An expression statement is expected to be
            > an assignment, a function/method call, or delete. All other expression
            > statements are considered errors."

            Thanks for checking.
            I guess the OP was hoping for more of an explanation.

            By the way, I can think of a couple more expression statements that are
            accepted by JSLint: pre/postfix increment and decrement, bit shifting,
            and '"use strict";' (the former two are not part of the Good Parts, and
            there are options to disallow them).

            > In the end, using expression statements can give you all the terseness
            > of a regular expression without the precision and power. It can be the
            > worst of both worlds. They don't pass our code reviews.

            I don't understand the comparison with regular expressions. Anyway, I'm
            not in any way advocating the use of these "flow control" expression
            statements. I happen to like them (but then, I also like Perl), others
            don't, no big deal. They are easy enough to avoid when I'm writing
            JSLint compatible scripts.

            stefan



            [Non-text portions of this message have been removed]
          • Dave
            Thanks MLorton and SWeiss for the good feedback. The discussion about type coercion was an off the topic disection of my analogy, not a succinct answer to the
            Message 5 of 12 , Mar 17, 2010
            View Source
            • 0 Attachment
              Thanks MLorton and SWeiss for the good feedback.

              The discussion about type coercion was an off the topic disection of my analogy, not a succinct answer to the '&&' as flow control issue.

              So thanks you two for staying on topic.

              Dave

              --- In jslint_com@yahoogroups.com, "Dave" <david.hampton@...> wrote:
              >
              > Many languages allow a convenience in scripting that allows an && to be used as flow control.
              >
              > var foo = [1,2,3,4];
              >
              > foo[0] && fop = foo.shift(); //assigns the first element of foo to fop, if it exists.
              >
              > Conversely, an || statement can be used for alternate functionality.
              >
              > JavaScript also allows this, but jslint does not. I'm curious as to why.
              >
              > Dave
              >
              > P.S., this may have been answered asked before, but it seems that the search functionality of YAHOO! Groups scrubs the '&' character...
              >
            • Michael Mikowski
              ... Sorry it didn t help you Dave. ________________________________ From: Dave To: jslint_com@yahoogroups.com Sent: Wed, March 17,
              Message 6 of 12 , Mar 17, 2010
              View Source
              • 0 Attachment
                Type coercion certainly seemed on-topic, as the comment for the following line is wrong precisely because of it:


                > foo[0] && fop = foo.shift(); //assigns the first element of foo to fop, if it exists.

                Sorry it didn't help you Dave.




                ________________________________
                From: Dave <david.hampton@...>
                To: jslint_com@yahoogroups.com
                Sent: Wed, March 17, 2010 3:28:09 PM
                Subject: [jslint] Re: && as flow control


                Thanks MLorton and SWeiss for the good feedback.

                The discussion about type coercion was an off the topic disection of my analogy, not a succinct answer to the '&&' as flow control issue.

                So thanks you two for staying on topic.

                Dave

                --- In jslint_com@yahoogro ups.com, "Dave" <david.hampton@ ...> wrote:
                >
                > Many languages allow a convenience in scripting that allows an && to be used as flow control.
                >
                > var foo = [1,2,3,4];
                >
                > foo[0] && fop = foo.shift(); //assigns the first element of foo to fop, if it exists.
                >
                > Conversely, an || statement can be used for alternate functionality.
                >
                > JavaScript also allows this, but jslint does not. I'm curious as to why.
                >
                > Dave
                >
                > P.S., this may have been answered asked before, but it seems that the search functionality of YAHOO! Groups scrubs the '&' character...
                >




                [Non-text portions of this message have been removed]
              • pauanyu
                I am not Douglas, so I cannot speak for him, but here is my opinion on the matter. I believe the reason JSLint does not accept using && and || for flow control
                Message 7 of 12 , Mar 18, 2010
                View Source
                • 0 Attachment
                  I am not Douglas, so I cannot speak for him, but here is my opinion on the matter.

                  I believe the reason JSLint does not accept using && and || for flow control is because they are usually misunderstood and confusing to people who are not experienced with JavaScript.

                  I have seen some people who assumed that those two operators return true or false, not the operands. Until you have sufficient knowledge and experience with JavaScript, using those operators for flow control can be very confusing.

                  Which brings me to my second point: style. JSLint, in addition to checking for genuine errors, also occasionally enforces style conventions as well, usually with the goal of making your code more readable.

                  Compare these two blocks of code:

                  (typeof foo === "function") && foo();

                  if (typeof foo === "function") {
                  foo();
                  }

                  Although the first is certainly more concise, it is also confusing to people who do not understand how boolean operators work in JavaScript. On the other hand, almost everybody understands how "if" blocks work. As a consequence, the second version is less confusing, though it also consumes more space.

                  Personally, I like using the boolean operators for flow control, but I believe the issues above are why JSLint forbids it.

                  --- In jslint_com@yahoogroups.com, "Dave" <david.hampton@...> wrote:
                  >
                  > Many languages allow a convenience in scripting that allows an && to be used as flow control.
                  >
                  > var foo = [1,2,3,4];
                  >
                  > foo[0] && fop = foo.shift(); //assigns the first element of foo to fop, if it exists.
                  >
                  > Conversely, an || statement can be used for alternate functionality.
                  >
                  > JavaScript also allows this, but jslint does not. I'm curious as to why.
                  >
                  > Dave
                  >
                  > P.S., this may have been answered asked before, but it seems that the search functionality of YAHOO! Groups scrubs the '&' character...
                  >
                Your message has been successfully submitted and would be delivered to recipients shortly.