+!! operator in an if statement

后端 未结 6 1990
旧巷少年郎
旧巷少年郎 2020-12-29 18:31

I was reviewing the code for an angularjs factory to better understand how it works. The code contains an if statement that I don\'t fully understand.

I

相关标签:
6条回答
  • 2020-12-29 19:02

    Meanwhile, ^ is the bitwise XOR operator.

    When dealing with numbers smaller than 2, ^ will work like a boolean OR (||) if you consider 0 = false and 1 = true.

    0 讨论(0)
  • 2020-12-29 19:07

    This is a horribly unreadable way to write out the boolean value of a variable, and then convert it using unary conversion to give a 0/1 number result.

    Consider:

    +!!true; //this converts true to false, then to true again, and true is 1 when converted
    +!!0; //converts 0 (falsy) to true, then false, and then the numeric 0
    

    Technically speaking !! is not its own operator, it's just the NOT (!) operator twice.

    Unary conversion: ECMA spec doc a unary plus attempts to convert to an integer. Number() would also be a valid conversion.

    0 讨论(0)
  • 2020-12-29 19:09

    !! converts a value to a boolean (true or false). + then converts that boolean to a number, either 1 for true or 0 for false.

    > +true
    1
    > +false
    0
    

    Personally I find it clearer to write something like this, when dealing with two booleans:

    if (!config.template == !config.templateUrl) {
      throw ...
    }
    

    Code clarity and readability be damned, apparently.

    0 讨论(0)
  • 2020-12-29 19:11

    ! is the logical not operator. It is a unary operator that converts its operand to a boolean and then negates it. !! is just that operator twice, the second ! undoes the negation, so the end result is just conversion to a boolean.

    + is the unary plus operator, which converts it's operand to a number. In the case of a boolean, false becomes 0, and true becomes 1.

    So, +!!(expression) evaluates to 1 if the expression is truthy and 0 if the expression is falsy.

    0 讨论(0)
  • 2020-12-29 19:13
    if ((+!!config.template) + (+!!config.templateUrl) !== 1) {
    
                0            +         0               !== 1  true
                0            +         1               !== 1  false
                1            +         0               !== 1  false
                1            +         1               !== 1  true
    

    is equal to

    if (!config.template === !config.templateUrl) {
    

    despite the content of the two properties.

    0 讨论(0)
  • 2020-12-29 19:16

    +!! uses implicit conversion to cast a value as a 0 or 1 depending on its boolean value

    For the most part, this is to check for existence. For example, an empty string is false (!!"" === false), and so is undefined, and a number of others. Those are the main two though

    "Falsey" conversions

    +!!""        ===   0
    +!!false     ===   0
    +!!0         ===   0
    +!!undefined ===   0
    +!!null      ===   0
    +!!NaN       ===   0
    

    "Truthy" conversions

    +!!1         ===   1
    +!!true      ===   1
    +!!"Foo"     ===   1
    +!!3.14      ===   1
    +!![]        ===   1
    +!!{}        ===   1
    

    if ((+!!config.template) + (+!!config.templateUrl) !== 1)

    Hopefully this is making more sense at this point. The object config has two properties we are examining. .template and .templateUrl. The implicit cast to a 0 or 1 using +!! is going to be added and then compared to ensure that it is not 1 (which means it is either 0 or 2) - the properties can either both be on or off but not different.

    The truth table here is as follows:

    template    templateUrl    (+!!) + (+!!)     !==1
    "foo"       "foo"              1 + 1         true
    undefined   undefined          0 + 0         true
    undefined   ""                 0 + 0         true
    ""          undefined          0 + 0         true
    12          ""                 1 + 0         false
    ""          12                 0 + 1         false
    undefined   "foo"              0 + 1         false
    ""          "foo"              0 + 1         false
    "foo"       ""                 1 + 0         false
    "foo"       undefined          1 + 0         false
    

    A much simpler method to all of this would have been to just use the implicit boolean conversion

    if (!config.template === !config.templateUrl)
    
    0 讨论(0)
提交回复
热议问题