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

Re: [jslint] && as flow control

Expand Messages
  • 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 1 of 12 , Mar 12, 2010
    • 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 2 of 12 , Mar 17, 2010
      • 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 3 of 12 , Mar 17, 2010
        • 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 4 of 12 , Mar 18, 2010
          • 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.