Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does CoffeeScript's existential operator work?

Coffeescript uses the existential operator to determine when a variable exists, and in the coffeescript documentation it shows that something? would compile to something !== undefined && something !== null however I noticed that my version of coffeescript was only compiling this to something !== null so I wrote a test to see how this would effect my code

taco = undefined 

if taco?
    console.log "fiesta!"
else 
    console.log "No taco!"

which compiled to

// Generated by CoffeeScript 1.4.0
(function() {
  var taco;

  taco = void 0;

  if (taco != null) {
    console.log("fiesta!");
  } else {
    console.log("No taco!");
  }

}).call(this);

and outputted the somewhat unexpected No taco! so my question is two fold. Why does coffeescript no longer check for the value being undefined and why is this suficiant?

like image 515
Loourr Avatar asked Jun 22 '13 18:06

Loourr


1 Answers

The documentation says this about ?:

CoffeeScript's existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby's nil?

so of course this will say "No taco!":

taco = undefined 
if taco?
    console.log "fiesta!"
else 
    console.log "No taco!"

Your taco is explicitly undefined so taco? is false.

CoffeeScript implicitly declares variables so the JavaScript form of ? is context dependent. For example, if you just say only this:

if taco?
    console.log "fiesta!"
else 
    console.log "No taco!"

you'll see that taco? becomes typeof taco !== "undefined" && taco !== null. You still see the "is it null" check (in a tighter form) but there's also the "is there a var taco" check with typeof; note that the typeof taco test also checks for taco = undefined so a stricter !== test can be used to see if taco is null.

You say this:

I noticed that my version of coffeescript was only compiling this to something !== null

but that's not what it is doing, it is actually compiling to something != null; note the use of "sloppy" type converting inequality (!=) versus the strict inequality (!==) that you claim is there. The difference between != and !== is important here since:

  • Null and Undefined Types are == (but not ===)

So if you know that variable v has been declared (i.e. there is var v somewhere) then v != null is sufficient to check that v is neither null nor undefined. However, if you do not know that v has been declared, then you need a typeof check to avoid a ReferenceError when you try to compare an undeclared variable with null. Consider this JavaScript:

if(taco != null) {
    console.log("fiesta!");
} else {
    console.log("No taco!");
}

That will throw a ReferenceError in your face since taco does not exist. This:

if(typeof taco !== "undefined" && taco !== null)
    console.log("fiesta!");
} else {
    console.log("No taco!");
}

on the other hand is fine since the typeof check guards against trying to access something that hasn't been declared. I don't think you can construct the first one in CoffeeScript without embedding JavaScript using backticks.

like image 107
mu is too short Avatar answered Oct 17 '22 02:10

mu is too short