Existential operator ? can be used in three useful ways in CoffeeScript.

Checking the existence of a variable

In JavaScript there is no built-in way of checking the existence of a variable. You can try testing the existence with if(variable){...} but it won’t work in these cases:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if ( 0 ){ console . log ( 'this will not print' ); } if ( "" ){ console . log ( 'this will not print' ); } if ( false ){ console . log ( 'this will not print' ); } // abc was never declared if ( abc ){ //ReferenceError: abc is not defined }

The correct way to test if variable was both declared and initialized:

1 2 3 if ( typeof variable !== 'undefined' && variable !== null ){ console . log ( 'variable was declared and initialized with a value' ); }

You may be tempted to use direct comparison with undefined :

1 if ( variable !== undefined ...

But this is asking for trouble because in EcmaScript 3 (all older browsers, such as IE 6-8) undefined can be overwritten:

1 2 3 4 5 window . undefined = 'pancakes' ; if ( 'pancakes' === undefined ){ console . log ( 'This will print, if you are unfortunate enough to use IE 6-8' ); }

All ES5 compatible browsers have undefined immutable, i.e. it can’t be changed, but it’s better to play it safe.

CoffeeScript has a syntactic shortcut for testing existence:

CoffeeScript 1 2 if variable ? console . log ( 'variable is both declared and initialized with a non-null value' );

This code will be transpiled to:

1 2 3 if ( typeof variable !== "undefined" && variable !== null ) { console . log ( 'If variable was both declared and initialized with a non-null value' ); }

Conditional assignment

What if you want to initialize a variable only if it has not been already initialized? In JavaScript you’d usually do something like:

1 2 3 4 5 6 function getUserLocale (){ if ( this . locale == null ){ this . locale = DB . getLocaleByUser ( User . current ); } return this . locale ; }

This technique caches the result of an expensive computation or database query in a variable. In above example, all subsequent getUserLocale function calls will not query the database. The important part is comparing with null using == , rather than === , because == will evaluate to true if variable is either undefined or null .

Such cache on first call pattern is widely used in many programming languages, but CoffeeScript has a special syntax for it:

CoffeeScript 1 2 getUserLocale = -> @locale ?= DB . getLocaleByUser ( User . current )

?= is the operator that performs conditional assignment.

This will be transpiled to roughly the same JS as above, using ternary operator:

1 2 3 getUserLocale = function () { return this . locale != null ? this . locale : this . locale = DB . getLocaleByUser ( User . current ); };

What if you try to conditionally assign an undeclared variable? If you try this:

CoffeeScript 1 2 # abc is not declared abc ?= 99

This will result in a compile-time error: the variable "abc" can't be assigned with ?= because it has not been declared before . This compile-time checking is very helpful, because it prevents a ReferenceError at run time.

If you know Ruby, ||= is the same thing there.

Safe property / function chaining

Chaining function calls is a great way to write terse yet fluent code. A good example is working with jQuery:

1 $ ( '#header' ). css ( 'color' , '#fadfad' ). show ( 'slow' ). off ();

This is made possible because these jQuery functions return a reference to this . But what if one of the function returns null or undefined ?

1 var zip = User . current . address . zip

If current user’s address is null or undefined , the .zip property call will result in TypeError .

A simple but ugly solution would be to use a lot of if checks:

1 2 3 4 5 var zip = null ; if ( User . current != null && User . current . address != null ){ // only now this is safe zip = User . current . address . zip ; }

But this can quickly get out of hand with deep nesting.

CoffeeScript has a safe way of accessing long property chains using ?. variant of existential operator:

CoffeeScript 1 zip = User . current ? . address ? . zip

This will either soak up the null or undefined references and safely return undefined or return the final property value. In our case the generated code looks like this:

1 2 3 var zip , _ref ; zip = ( _ref = User . current ) != null ? _ref . address . zip : void 0 ;

What is this weird void 0 thing? This is to fight the pre AS5 undefined mutability I referred to earlier. JavaScript defines void as a unary operator that returns undefined for any argument. In other words, CoffeeScript compiler uses a set of nested ternary operators to safely return either last property value or undefined with void 0 .

Calling a function safely works similarly:

CoffeeScript 1 noSuchFunction ? ()

This transpiles to:

1 2 3 if ( typeof noSuchFunction === 'function' ) { noSuchFunction (); }

Key thing to take away here is that CoffeeScript first tests that callable function is defined and is a function. It does this using typeof bla === 'function' . The function is called only if it is defined.

Safe function invocation can be chained as well with other function or property calls:

example from coffeescript.org 1 lottery . drawWinner ? (). address ? . zip

This transpiles to:

1 2 3 4 5 6 var zip , _ref ; zip = typeof lottery . drawWinner === "function" ? ( _ref = lottery . drawWinner (). address ) != null ? _ref . zipcode : void 0 : void 0 ;

Drawing analogy with Ruby-on-Rails ActiveSupport, the safe chaining can be seen as try method.

Conclusion:

CoffeeScript existential operator is a useful tool to cut down the verbosity of JavaScript when dealing with existence and null checks. It also can be used to shield inexperienced JavaScript developers from JavaScript bad parts.