14

according to the coffee script site

console.log(s) if s?

should generate

if (typeof s !== "undefined" && s !== null) {
    console.log(s);
}

But what is showing up in my browser is

  if (s != null) {
      return console.log(s);
  }

Using coffee-script-source (1.6.2), coffee-rails (3.2.2), rails-backbone (0.7.2), rails (3.2.13)

Here is my coffee script function. any thoughts on why I am not getting what coffee script site says I should??

window.p = (s) ->
    console.log(s) if s?
peter cooke
  • 987
  • 3
  • 10
  • 28
  • Interesting. But potentially correct. Can `s` be undefined in your situation? It is defined as a function argument. – Thilo Sep 05 '13 at 02:40
  • possible duplicate of [CoffeeScript Undefined](http://stackoverflow.com/questions/9929306/coffeescript-undefined) (not really the question, but the answers and comments discuss this detail) – Thilo Sep 05 '13 at 02:43

2 Answers2

31

If you say just a bare:

console.log(s) if s?

then you will indeed get the JavaScript you're expecting (demo):

if (typeof s !== "undefined" && s !== null) {
  console.log(s);
}

However, if s is a known variable such as here:

f = (s) -> console.log(s) if s?

then you'll get (demo):

if (s != null) {
  //...
}

for the s? test.

So why the difference? In the first case, CoffeeScript cannot guarantee that there is an s variable in existence anywhere so it must do a typeof s check in order to avoid a ReferenceError exception.

However, if s is known to exist because it is a function parameter or has been assigned to as a local variable (so that CoffeeScript will produce a var s), then you don't need the typeof s check since you cannot, in this case, get a ReferenceError.

That leaves us with s !== null versus s != null. Dropping down to non-strict inequality (s != null) allows you to check if s is undefined or null with a single comparison. When you check typeof s !== "undefined", you wrapping the undefined test in with the "is there an s variable" check and a strict s !== null test is all that you need to check for null.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 2
    By Javascript (Ecmascript) standards `undefined` and `null` are `==` equal, so `s==null` is an old and well established usage. But many lint standards object to the use of `==`. It's one the issues you have address if compiled coffeescript has to be lint approved. – hpaulj Sep 05 '13 at 20:00
2

You're right,

(s) -> console.log(s) if s?

console.log(x) if x?

compiles to

(function(s) {
  if (s != null) {
    return console.log(s);
  }
});

if (typeof x !== "undefined" && x !== null) {
  console.log(x);
}

It looks like the CoffeeScript compiler is optimizing the Javascript a little bit for you, because in the case of a function argument like this, typeof s will never be undefined as s is defined right there in the function signature, even if its value is null.

nicolaskruchten
  • 26,384
  • 8
  • 83
  • 101
  • here is live example http://coffeescript.org/#try:(s)%20-%3E%20console.log(s)%20if%20s%3F%0A%0Aconsole.log(x)%20if%20x%3F – OzzyCzech Mar 12 '14 at 13:54