Equality of ES6 Template Literal VS concatenated string

Viewed 155
let x = ‽; // "‽" Could be any type(String, Array, Object, ...) The goal is to make the statement true 

`${x}` !=  '' + x // true

`${x}` !== '' + x // true

What should we assign to X to make the statements true?

I'm thinking it's not possible to make it true, but is there any exception?

2 Answers

You need a value that serializes to a different value every time it's converted to a string.

const x = {
  [Symbol.toPrimitive]: (y => () => y++)(0),
};

console.log(`${x}` !== '' + x);

Felix's answer covers one absolutely valid approach, but I'll add another one here that doesn't require incrementing or random values.

`${x}`

converts x to a string using ToString, which in the case of x being an object, does ToPrimitive(argument, string).

'' + x

on the other hand uses ApplyStringOrNumericBinaryOperator, which does ToPrimitive(rval).

You can take advantage of that difference in the 2nd parameter of the function. For example:

x = {
  [Symbol.toPrimitive](hint) {
    if (hint === "string") {
      return 'a';
    } else {
      return 'b';
    }
  },
};

and now in this case

`${x}` === 'a' // true
'' + x === 'b' // true

You can also see this without Symbol by directly using toString and valueOf:

x = { 
  toString(){ return 'a'; }, 
  valueOf(){ return 'b'; },
};

which produces the same thing as the last example, because valueOf is the default unless a string value is explicitly hinted, as in the case for ${x}.

Related