Rare Javascript Operators

by Timmy Willison

All the operators!

Arithmetic, Assignment, Bitwise, Comparison, Logical, & String

(+, -, *, /, %, ++, --, unary -, unary +)
(=, *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, |=)
(&, |, ^, ~, <<, >>, >>>)
(==, !=, ===, !==, >, >=, <, <=)
(&&, ||, !)
(+ and +=)
Operators docs

I can haz lots!


Smooth Operator

Smooth Operator

Operator precedence

Javascript has 17 levels of precedence

  1. Member(., []), new
  2. function call()
  3. ++ and --
  4. !, ~, unary +, unary - (e.g. -1), typeof, void, delete
  5. *, /, %
  6. + and -
  7. bitwise shifting (<<, >>, >>>)
  8. relational(<, <=, >, >=), in, instanceof
  9. equality(==, !=, ===, !==)
  10. bitwise-and (&)
  11. bitwise-xor (^)
  12. bitwise-or (|)
  13. logical-and (&&)
  14. logical-or (||)
  15. conditional (?:)
  16. all assignment operators
  17. comma (,)

Bitwise Operators

Are they useful in the real world?

The ~ operator

-( n + 1 )

Tilde is useful!

We can use for any functions that return -1

var foo = "baz",
    checkFoo = foo.indexOf("bar");
// So instead of...
if ( checkFoo !== -1 ) {

}
// We can do
if ( ~checkFoo ) {

}


~pres.indexOf("example")




Next one will floor you!

0-fill shift right(>>>)

Here's another useful bitwise operator.

A quick Math.floor for positive values (make sure it's positive tho)!

Example.notAwesome >>> 0

Here's an implementation from MDC of forEach

Array.prototype.forEach = function( fun, thisp ) {
  var t, len;
  if ( this === void 0 ||
      this === null ||
      typeof fun !== "function" ) {
    throw new TypeError();
  }

  t = Object(this);
  len = t.length >>> 0;
  for ( var i = 0; i < len; i++ ) {
    if ( i in t ) {
      fun.call(thisp, t[i], i, t);
    }
  }
};



Special Operators

  • Conditional Operator (Ternary)

    (condition ? ifTrue : ifFalse)
  • Comma Operator

    (,)
  • Operators that are keywords

    (function, delete, get, in, instanceof, let, new, set, this, typeof, void, yield)

Note: Technically, get and set are not really called anything in the spec, but are part of Property Descriptor defintions in Object Initialiser/PropertyAssignment. Mozilla Developer Network calls them operators. Either way, they're fun.

get

Binds an object property to a function that will be called when that property is looked up.

var o = {
  get latest () {
    return this.log.length > 0 ?
      this.log[ this.log.length - 1 ] :
      null;
  },
  log: []
};
o.log[0] = "wowowow!";
o.latest === "wowowow!";

set

Binds an object property to a function to be called when there is an attempt to set that property

var o = {
  set current ( str ) {
    return this.log[this.log.length] = str;
  },
  log: []
};

o.current = "foo";
o.log[0] === "foo";
delete o.current;

The downside

You've probably used comma before

for (var i = 0, j = 9; i <= 9; i++, j--) {
  document.writeln("a["+i+"]["+j+"] = " + a[i][j]);
}

That is different than (not an operator here):

var i, l, foo, bar, baz;
Use it when you want multiple expressions in a location that requires a single expression.

Wicked awesome usage (James Padolsey)

Detect IE in JS using conditional comments (No block in that while?!?)

var ie = (function(){
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while (
        div.innerHTML = '',
        all[0]
    );

    return v > 4 ? v : undef;
}());

Hot debate! == vs ===

You know the difference. == attempts to coerce the values before comparison. So which should you use?

0 === 0 // true
0 == '0' // true
0 === '0' // false
0 == false // true
0 == '' // true
null == undefined // true
null === undefined // false


Equals benchmark without coercion
Equals benchmark with coercion

Short answer: strict equals (===) has better performance. JSPerf stats

  • Chrome's V8 engine has significantly lower performance with double equal when type coercion does occur( overall performance is unmatched in V8 ).
  • Safari's JavascriptCore is odd. == wins for no type coercion and === wins with type coercion.
  • IE6-8 has consistently better performance with === whether type coercion is done or not.
  • Opera also has consistently better performance with ===, but type coercion significantly slows both.
  • Firefox 3.6's Spidermonkey had similar results to Chrome, but obviously with lower numbers.
  • The new Firefox 4 js engine (j├Ągermonkey) optimizes for ==, so it does win in this browser.
  • Strict equal(===) compresses to 1 byte just like (==) with gzip compression, so the argument that it takes up more space is not valid in that case.

Bang! (bam)

== is most often useful when doing comparison with null, also want to catch undefined.

Bambam

In most cases, it would also be useful for you to catch 0 and empty string...

!!example

function foo( arg ) {
  if ( arg != null ) {
    // Argument is present, but may be empty string or 0
  }
}
function foo( arg ) {
  if ( !!arg ) {
    // Argument is valid
  }
}
// Can be even shorter
function foo( arg ) {
  if ( arg ) {
    // 0, '', null, and undefined are "falsy"
  }
}

There are a few cases where === may not be adequate.

String literal vs string object

"abc" == new String("abc") // true
"abc" === new String("abc") // false

== will check the value, but they are not the same type.

typeof "abc" // "string"
typeof new String("abc") // "object"

Side note: The paradoxical number (NaN)

NaN == NaN // false
typeof NaN === "number" // true

var a = NaN;
a == NaN || a === NaN // false

isNaN( a ) // true, use this!

This is why we need isNaN()