开发者

An explanation of && shorthand in JavaScript

Using a watermark plugin for jQuery, I'm attempting to jslint and minimize the functions but I've come across syntax I have never seen before wherein there are expressions where there really ought to be an assignment or function call:

(function($) {

    $.fn.watermark = function(css, text) {

        return this.each(function() {

            var i = $(this), w;

            i.focus(function() {
                w && !(w=0) && i.removeClass(css).data('w',0).val('');
            })
                .blur(function() {
                    !i.val() && (w=1) && i.addClass(css).data('w',1).val(text);
                })
                .closest('form').submit(function() {
                    w && i.val('');
                });

            i.blur();
        });
    };

    $.fn.removeWatermark = function() {

        return this.each(function() {

            $(this).data('w') && $(this).val('');
        });
    };
})(jQuery);

I'm specifically interested in the following lines:

w && !(w=0) && i.removeClass(css).data('w',0).val('');

and

!i.val() && (w=1) && i.addClass(css).data('w',1).val(text);

Can someone expl开发者_开发技巧ain this shorthand and rewrite these functions in such a way that I could compare them to better to understand the shorthand myself?

Thank you.


Let's break each of the statements you're asking about down to their components:

w && !(w=0) && i.removeClass(css).data('w',0).val('');
  • w - Is w "true"? (checking for != 0 in this case)
  • !(w=0) - Set w to 0, take the opposite of the result so the && chain continues
  • i.removeClass(css).data('w',0).val('') - Remove the class, set the data to 0 clear the value.

!i.val() && (w=1) && i.addClass(css).data('w',1).val(text);
  • !i.val() - Is the input empty?
  • (w=1) - Set w to 1
  • i.addClass(css).data('w',1).val(text); - Add the class, set the data to 1 and set the text to whatever the watermark text is.

Both of these are just statements to really cut down on code, certainly at the expense of readability. If you're looking at a de-minified version this is very common, if you're not and this is the original, chase the author with a salad fork, the original should be more more readable than this IMO, though it's just fine for a minified version.


&& can be used as a "guard." Basically it means stop evaluating the expression if one of the operands returns a "falsy" value.

Negating an expression will convert it to a boolean value. Specifically one that is a negation of the expression depending on whether it's 'truthy' or 'falsy'.

w && !(w=0) && i.removeClass(css).data('w',0).val('');

Basically says:

w is "truthy" (defined, true, a string, etc.)
AND set w to zero + convert the expression to true (because (w=0) would evaluate to 0, which is falsy)
AND evaluate i.removeClass(css).data('w',0).val('')


These can be rewritten as:

// w && !(w=0) && i.removeClass(css).data('w',0).val('');
if (w) {
    if (!(w=0)) {
        i.removeClass(css).data('w',0).val('');
    }
}

//!i.val() && (w=1) && i.addClass(css).data('w',1).val(text);
if (!i.val()) {
    if (w=1) {
        i.addClass(css).data('w',1).val(text);
    }
}

Using && like this is just a shorthand for using nested ifs. It's advantages being:

  1. Uses marginally fewer characters than the exploded nested ifs, decreasing the payload that's delivered to the browser.
  2. Can be faster to read for the trained eye.

Though, I must say that the above examples are an abuse of this shorthand because the conditionals used are fairly complex. I only resort to this shorthand when I need to check a chain of simple things like in the following example:

function log(s) {
    window.console && console.log && console.log(s);
}


&& is And. It's for comparison / compound conditional statements. It requires that both conditions in an if statement be true. I do not think there is another way to rewrite it - that is the syntax for And.


With respect to:

w && !(w=0) && i.removeClass(css).data('w',0).val('');

the code:

!(w=0) && i.removeClass(css).data('w',0).val('');

will only execute if

w

is truthy.


Using

w && !(w=0) && i.removeClass(css).data('w',0).val('');

for this explanation, it allows you to string multiple commands together while ensuring that each is true.

This could also be represented by:

if (w) {

    w = 0;
    i.removeClass(css).data('w',0).val('');
}

It first makes sure w evaluates to true, and if it is, it checks if w=0 is not true (w != 0). If this is also true, then it goes on to the actual command.

This is common shorthand in a lot of languages that use lazy evaluation: If the next evaluation is put in with and (&&) then the following commands will not be executed if it returns false. This is useful in the sort of situations where you only want to perform an action on something if the previous statement returns true, like:

if (object != null && object.property == true)

to make sure object isn't null before using it, otherwise you would be accessing a null pointer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜