String(symbol)

# Erik Arvidsson (8 years ago)

Right now String(symbol) throws because it uses ToString which is spec'ed to throw.

I'm suggesting that we special case String(value) to do a type check for Symbol and return the same string as Symbol.prototype.toString.call(value) does.

people.mozilla.org/~jorendorff/es6-draft.html#sec-string-constructor-string-value

The motivation for this is that String(value) is pretty explicit and was in ES5 a safer way to stringify something than value.toString().

# Claude Pache (8 years ago)

+1. As I already noted last year, as currently specced, ad-hoc debugging code like alert("got argument: " + x) or alert("got argument: " + String(x)) will throw for symbols, while alert("got argument: " + x.toString()) will throw for null, undefined, and Object.create(null).

# Erik Arvidsson (8 years ago)

symbol + '' must continue to throw.

I was suggesting that String(symbol) should not throw.

This can be spec'ed as String( value ) checking the Type of the value and special case it in case of the value being a symbol.

# Allen Wirfs-Brock (8 years ago)

sounds good to me, I'll update the spec. accordingly

# Nathan Wall (8 years ago)

Out of mere curiosity, why is it desired that symbol + '' throw?

# Rick Waldron (8 years ago)
# Allen Wirfs-Brock (8 years ago)

On Aug 13, 2014, at 8:45 AM, Nathan Wall wrote:

Out of mere curiosity, why is it desired that symbol + '' throw?

Minimize the chance that somebody might code:

var newName = somePropertyKey+"_stuff";

not realizing that somePropertyKey might be a Symbol. We don't want to silently crete a string property name from a symbol.

# Jeff Walden (8 years ago)

With this change, as far as I can tell there's no concise operation directly corresponding to the ToString abstract operation. The best that seems possible is some horribly indirect operation like (v) => Error.prototype.toString.call({ name: v, message: "" }). That seems undesirable to me. I'm not convinced that having String deviate from ToString is a good thing.

# Domenic Denicola (8 years ago)

Why would it be useful, from a programmer's perspective, to expose ToString directly? It is just a spec-internal thing, and the reason this change is made is because it is no longer very useful to directly expose that spec-internal thing given how it interacts with symbols.

# Jeff Walden (8 years ago)

On 08/26/2014 08:48 AM, Domenic Denicola wrote:

Why would it be useful, from a programmer's perspective, to expose ToString directly?

People will always want to polyfill, or prototype in advance of proposal for standardization. No matter how internal the operation might be, it's heavily used by DOM specs and other similar sorts of things. And I have difficulty seeing why many such APIs would want to stringify incoming symbols, to switch away from using ToString.

# Claude Pache (8 years ago)

Personally, I use the following expression in order to coerce a variable to a string:

var obj = this + ''

and its in-place variant:

x += ''

I think it'll continue to work in ES6.

# Brendan Eich (8 years ago)

Agreed, this is the correct-and-most-concise way to do it. It should throw on symbols, that's important.

Having String(sym) not throw is a win for other reasons Arv identified, but using String(any) to invoke ToString is verbose and fragile, because String could be rebound :-P. Use +'' if you want ToString in the language, I say.

# Domenic Denicola (8 years ago)

x+'' produces different results than ToString when x = { toString() { return '5'; }, valueOf() { return 10; } }

# Jeff Walden (8 years ago)

On 08/26/2014 09:14 AM, Brendan Eich wrote:

Agreed, this is the correct-and-most-concise way to do it.

It's not the most correct way to do it. a + "" performs ToPrimitive(a, hint = None), whereas ToString(a) performed ToPrimitive(a, hint = String). The former consults valueOf, then toString, the latter the reverse.

using String(any) to invoke ToString is verbose and fragile, because String could be rebound :-P.

Generally polyfills are fine with that limitation, and only us language pedants need worry/care about String being rebound. All the array-method polyfills we've provided on MDN depend on non-rebinding of some builtin function or other. It's not that big a deal.

# André Bargull (8 years ago)

If x is an object, x + '' performs ToString(ToPrimitive(x, <no hint>)), whereas String(x) performs ToString(ToPrimitive(x, hint String)). So both expressions are not always interchangeable.

# Brendan Eich (8 years ago)

Brendan Eich wrote:

Use +'' if you want ToString in the language, I say.

asm.js points the way on other explicit conversion forms:

  • ToString(x) is x+''
  • ToNumber(x) is +x
  • ToInt32(x) is ~~x
  • ToBoolean(x) is !!x
# Brendan Eich (8 years ago)

Jeff Walden wrote:

It's not the most correct way to do it. a + "" performs ToPrimitive(a, hint = None), whereas ToString(a) performed ToPrimitive(a, hint = String). The former consults valueOf, then toString, the latter the reverse.

Argh, I had forgotten about the no-hint case there. It seems wrong still, but I forget the details from ES1 era.

Domenic's question of why you want an explicit ToString in the language remains. If there's a strong reason for it, Reflect.toString might be the answer.

# Claude Pache (8 years ago)

Le 26 août 2014 à 17:39, Jeff Walden <jwalden+es at MIT.EDU> a écrit :

On 08/12/2014 11:07 PM, Allen Wirfs-Brock wrote:

sounds good to me, I'll update the spec. accordingly

On Aug 12, 2014, at 7:39 PM, Erik Arvidsson wrote:

I was suggesting that String(symbol) should not throw.

This can be spec'ed as String( value ) checking the Type of the value and special case it in case of the value being a symbol.

With this change, as far as I can tell there's no concise operation directly corresponding to the ToString abstract operation. The best that seems possible is some horribly indirect operation like (v) => Error.prototype.toString.call({ name: v, message: "" }). That seems undesirable to me. I'm not convinced that having String deviate from ToString is a good thing.

Jeff

What about String.prototype.concat?

const ToString = ''.concat.bind('')