CoffeeScript Existential Operator and this

2020-02-10 18:59发布

问题:

I noticed something a little odd with the CoffeeScript compilier and was wondering if this was correct behavior or not. If it is correct I'm curious why there is a difference..

Given the following CoffeeScript:

if @myVar?
  alert myVar

I was expecting it to compile to JavaScript like this:

if (typeof this.myVar !== "undefined" && this.myVar !== null) {
  alert(myVar);
}

But instead what the CoffeeScript compiler outputs is this:

if (this.myVar != null) {
  alert(myVar);
}

If I don't reference this (or any other parent object), the CoffeeScript compiles as I would expect.

Is this the correct behavior? If so, why does it work different when using this?

Edit:

To add a little more clarification. This doesn't happen with only this, but any other properties of objects. For instance, if I were replace the above CoffeeScript with what's below it still would compile with only "!= null"...

if myVar.myProp?
  alert myVar

回答1:

In the case of:

myVar = 10
if myVar?
  alert myVar

Coffeescript compiler is able to see that myVar is really defined in the first line, so it can omit typeof myVar !== "undefined" check.

if (myVar !== null) {
  alert(myVar);
}

But in this case:

if myVar?
  alert myVar

compiler can't guarantee that myVar is actually defined, so extra check is required:

if (typeof myVar !== "undefined" && myVar !== null) {
  alert(myVar);
}

So, the answer is: Coffeescript compiler tries to be smart to produce efficient code.

EDIT The way Coffeescript deals with properties is also correct: this.prop will return undefined if property is not defined. != will convert it to null. That is why we don't need additional check.
In few words:

  • accessing undefined variable throws exception -- need to check typeof
  • accessing undefined property returns undefined -- just != is enough