Is this not redundant



  • Just taking a peak at the JS file on my works website and found this: 
     
    function _**********_h***************s()
    {
    if( this.m_array != null && this.m_array.length > 0 && this.m_currIndex < this.m_array.length )
    {
    return true;
    }
    return false;
     
    Correct me if I'm wrong but if the m_array.length >0 then it will mean it is not null anyway? - So there doing a double check to make sure that the array is empty? 


  • @Cratig said:

    Just taking a peak at the JS file on my works website and found this: 
     
    function __h*****s()
    {
    if( this.m_array != null && this.m_array.length > 0 && this.m_currIndex < this.m_array.length )
    {
    return true;
    }
    return false;
     
    Correct me if I'm wrong but if the m_array.length >0 then it will mean it is not null anyway? - So there doing a double check to make sure that the array is empty? 

     I don't know how Javascript handles that, but Java would throw an exception if you try to access array.length while array==null.
     



  • I think this is what you call 'rather safe then sory' code.

     
    If you put in a array then your right, however if you put in something that used to be a array then it's either null or false or whatever language your using prefers.

    those generally don't have a langth attribute and will chrash your program. First checking if it isn't null will save you from that faith in a lazy language.
     



  • The real redundancy is using an if to return a boolean value. Just return the test as is. As it's trivial it's equally readable.



  • @ammoQ said:

    I don't know how Javascript handles that, but Java would throw an exception if you try to access array.length while array==null.

     

    Javascript short-circuits, like any sane language.
     



  • Yes of course, but what if you take out the first part of the test, the part that the OP considers "redundant"?



  • @ammoQ said:

    Yes of course, but what if you take out the first part of the test, the part that the OP considers "redundant"?

    Javascript would actually throw an exception also. It would be caught, and you'd either get a "script error" dialog, or that little yellow exclaimation point down on the status bar.



  • @Cratig said:

    Correct me if I'm wrong but if the m_array.length >0 then it will mean it is not null anyway? - So there doing a double check to make sure that the array is empty? 

    The null test is to ensure that m_array has been set on the object. If you try to access m_array.length, when m_array doesn't exist, javascript will throw.

    Remember, javascript is a prototype based language, not an object oriented one. There is no class definition and no guaranteed constructor, and therefore no way of ensuring that m_array actually exists on the object. You need to test for its existence before you use it. It would only be a redundant test only if m_array were previously guaranteed to exist.I'm guessing that this function is designed to be added to a pre-existing object, and m_array is therefore not guaranteed to previously exist.



  • If you're used to typed languages, JS has many surprises. Despite its C-like syntax, JS is more related to LISP than a member of the C-family. JS objects can be null and undefined, which is not the same thing. Remember, all objects in JS are associative arrays, i.e. hash table.

    this.a is simply a shortcut for this["a"] (not to be confused with this[a]).

    The value of this.a is undefined when nothing has ever be assigned to this slot. The value of this.a is null when null has been explicitely assigned.

    
    alert(this.a); // "undefined"
    this.a = null;
    alert(this.a); // "null"
    

    In light of this, it is never a good idea to compare to null. Null are rare because they only exist when explicitely assign! So instead of if( this.a != null .. ) use if( this.a ... )

    When undefined values are used in conditional expressions, the resulting value is undefined. Before you start making smart remarks about "undefined" = "file not found", recall that JS does not have types: there is no such thing as a boolean. So skipping the "this" fo brevity, the best way to implement the function is:

    function f() { return a && i < a.length; }

    This returns false if: a is undefined, or if a.length is undefined, or if i is undefined, or if a is null, or if i is null, or if i and a.length are numbers with former less than the latter. In other cases, it returns true. Like the original function, it returns true when i < 0, which is a WTF I kept intact. It doesn't matter much, because the function itself is redundant! All objects, including "arrays" are hash tables. If a is an object, then a[i] is a valid expression, although its value may be undefined. If an object has a "length" property it does not mean it is an array. Even if it is an array with a certain length, this doesn't doesn't imply that it has values for indexes between 0 and length. The notion "index out of bounds" does not exist in JS.

    a = [,,,1];

    This is an array of length 4, but a[0], a[1] and a[2] are undefined. Some samples where the function returns useless information:

    a = {length:2};
    i = 1;
    f(); // return true, but a[1] does not make sense
    

    a = "abc";
    i = 1;
    f(); // return true. On Mozilla, a[1] === "b"; on IE7, a[1] is undefined;

    a = [,,,,];
    i = 1;
    f(); // return true, however, a[1] is undefined.
    // a.length == 4 in MSIE; but 3 in Mozilla, which ignores tailing comma

    a = [1,2,3];
    i = -1;
    f(); // return true, but a[-1] is undefined.


    Don't say "That will never happen": those will be your famous last words. Murphy's law holds more strongly in the JS universe than anywhere else because it is uncompiled and untyped. The only way to truly test whether a[i] is a "valid" object is this:


    if( a && ( a[i] || a[i] === 0 ) ) {
       // do something with a[i]
    }

    Note the triple === which tests equality rather than identity, to allow for zero.



  • JavaScript is tricky, and fun.The other day, I was dynamically writing data into table cells like so:

    myTable.rows[i].cells[2].innerHMTL = "some stuff, etc";

    My data would never appear in the table. On the other hand, there was no error. It took me a moment to see that I had type innerHMTL, rather than the correct innerHTML; JavaScript happily gave the table cell my "property" and it's value.



  • Not only is JavaScript tricky and fun, When in combination with websites it's also very browser dependant.

    For instance, i had this super Ajaxy super thing i needed to put in a form, where i rewrote some options based on other choices. (in other words, a list of checkboxes that got re-wrote based on a dropdown list selection)

    everything nice and dandy, then the checkboxes needed to be replaced by a dropdown, because of design constraints.
    But since that's basically the same i kept most of the old code.

    So first i just used innerHTML on the select element to write new options into it.

    IE6&7 didn't register the new options when submitted.

    Then i rewrote a bit of the function and just rewrote the whole select form element.

    Firefox didn't liked this idea and wouldn't send it when submitted.

    So then i had to rewrite most of the code to actually do it all in JS, and create new options for the existing select form element.

     

    But then again, perhaps i should have been using the HTML DOM from the start instead of just inserting new HTML manually.



  • @stratos said:

    Not only is JavaScript tricky and fun, When in combination with websites it's also very browser dependant.

    For instance, i had this super Ajaxy super thing i needed to put in a form, where i rewrote some options based on other choices. (in other words, a list of checkboxes that got re-wrote based on a dropdown list selection)

    everything nice and dandy, then the checkboxes needed to be replaced by a dropdown, because of design constraints.
    But since that's basically the same i kept most of the old code.

    So first i just used innerHTML on the select element to write new options into it.

    IE6&7 didn't register the new options when submitted.

    Then i rewrote a bit of the function and just rewrote the whole select form element.

    Firefox didn't liked this idea and wouldn't send it when submitted.

    So then i had to rewrite most of the code to actually do it all in JS, and create new options for the existing select form element.

     

    But then again, perhaps i should have been using the HTML DOM from the start instead of just inserting new HTML manually.

    You just happened to have problems with something that's not actually related to Javascript, the language, at all. :)
    But it's true that adding options to a select has its issues.

     

    @JvdL said:

    stuff

    Note the existence of the typeof operator (which, contrary to common belief, is a unary operator, not a function), which will return "undefined" when a ariable is undefined. The fact that Javascript evaluates common "empty" values to false*, and that its || operator returns the first "true" value or the last one, make the sloppy typing in JS more bearable.

    A really tricky thing is that JS distinguishes between undefined and undeclared. Consider these two scripts:

    ============
    //one
    var foo;
    alert(foo);
    ============
    //two
    alert(foo);
    ============
     

    The first one will alert the string "undefined" because of JS's automatic type conversion (often more a curse than a blessing)
    The second one will throw an error, saying that foo is undefined! This behaviour is absent for "undeclared" properties in maps. In a sense, all possible properties you could even think of are implicitly declared (but not defined) in JS maps.

     *) but, interestingly, empty arrays and empty objects/maps evaluate to true. In fact, typeof Array -> "object"


Log in to reply