0

In CoffeeScript, the following statement evaluates to a JavaScript statement that is prefixed by an empty string.

I feel like there is an edge case with regards to type safety, but I can't think of it off the top of my head. In what case does the prefix make a difference?

CoffeeScript:

x = "#{foo} bar"

JavaScript:

x = "" + foo + " bar";
Kaushik Shankar
  • 5,491
  • 4
  • 30
  • 36
  • 2
    I am not 100% certain, but it's worth noting this bit of code I tried: `{a:'y'}+" thing"` => NaN but `""+{a:'y'}+" thing"` => "[object Object] thing". So my guess is that concatenating an object to an empty string calls `toString` on the object before concatenation – Brennan Nov 04 '14 at 02:25
  • 3
    It regards steps 7 and 8 of [the `+` operator's definition](http://ecma-international.org/ecma-262/5.1/#sec-11.6.1) and ensures concatenation (7) vs. addition (8). A contrived example is `"#{3}#{4}"`. With the empty string at the start of the expression (`"" + 3 + 4`), it results in `"34"`. Without it (`3 + 4`), the result is `7`. – Jonathan Lonowski Nov 04 '14 at 02:39
  • 2
    @Brennan: No. You fell prey to `{a:'y';}` being block syntax (see [these](http://stackoverflow.com/q/14115902/1048572) [questions](http://stackoverflow.com/q/17268468/1048572)). Try `({a:'y'})+" thing"` – Bergi Nov 04 '14 at 03:24
  • 1
    @JonathanLonowski, perfect explanation, thanks. Also, Bergi, thanks, great to know – Brennan Nov 04 '14 at 03:25
  • Thanks @JonathanLonowski for the link to the operator definition! I finally understood whats going on here! The catch here is that with `{} + " bar"` what actually happens is that it goes into the 8th option (converting to number) which in turn tries to coerce the ToPrimitive of the object as a number, which in turn is NaN! – Kaushik Shankar Nov 04 '14 at 17:48
  • 1
    @KaushikShankar Using `{}` adds some additional complexity since they have 2 uses in JavaScript. When written on its own, `{} + " bar"` is actually two statements, `{};` and `+" bar";`, with a [block](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block) and [unary `+`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus_(.2B)). The parenthesis Bergi mentioned make it an *Expression* and the `{}` an `Object` literal. `({}) + " bar"` results in `"[object Object] bar"`. – Jonathan Lonowski Nov 04 '14 at 18:18
  • @JonathanLonowski Thanks for the clarification! I see now why the `NaN` is the output; the `{}` returns `undefined` because its actually an invocation of a block, returning `undefined`, which is then converted to a number, and since `+ "bar"` is converted to `NaN` separately as a number as well, its sum is also `NaN`. – Kaushik Shankar Nov 04 '14 at 23:10

1 Answers1

1

It ensures that the expression is always evaluated as a string, preventing e.g. numerical addition instead of concatenation. In the case where a string only contains a single interpolated expression, it also effectively converts that expression to a string. A couple of examples:

x = 2
y = 3

typeof "#{x}" is string   # true since this compiles to "" + x

str2 = "#{x}#{y}" # We want the string "23" here, not the number 5
Joe Lee-Moyet
  • 1,804
  • 1
  • 20
  • 24