
ES6 Symbols in Depth - ponyfoo
http://ponyfoo.com/articles/es6-symbols-in-depth
======
tel
Hm, I sort of ignored these when diving into ES6 at first, but they're perfect
for making extensible sum types

    
    
        function match(t, matchers) {
          const variant = t[Symbol.for('variant')];
          return matchers[variant](t);
        }
    

Previously one had to make the sum look something like

    
    
        { _variant: String
        , _params: Obj
        }
    

to ensure that you could work generically with them and not have the _params
object accidentally clobber your variant. Underscore privates are nice, but...
obviously a hack.

------
hardwaresofton
I've also recently been reading this blog on MDN that covers pretty much all
the concepts in ES6:

[https://hacks.mozilla.org/category/es6-in-
depth](https://hacks.mozilla.org/category/es6-in-depth)

(note it's extremely similar to this one, both are guides on ES6 and cover
pretty much all the areas)

------
nailer
> Note that there was no new. The new operator even throws a TypeError when we
> try it on Symbol.

Why? That seems inconsistent with other JavaScript constructors.

~~~
thomasfoster96
It's because the Symbol() function is creating a primitive value, not an
object. There is no literal syntax for symbols, as there is for numbers,
strings, etc., and so the symbol function is how you make them. Having a
symbol constructor would be of little use (it'd be like using new Number())
and so it wasn't included.

~~~
kevincennis
Just to expand on that a bit for anyone who might not know this:

    
    
        var s = new String('foo');
        typeof s; // 'object'
    

That is, when you use the `new` keyword, you get back an object instead of a
primitive. Since symbols are _always_ primitives, disallowing the `new`
keyword actually _prevents_ inconsistency with the rest of the language in the
sense that it doesn't allow you to create non-objects with a constructor.

~~~
draw_down
Strings are always primitives too, but you can call `new String` and receive
an object, not an error. This is just straight-up inconsistent, I don't see
the point of arguing otherwise.

~~~
thomasfoster96
Take a look at this[0] with regards to strings.

I'm not really sure why you'd use new String anyway - it won't always act as a
string primitive. Rather than making Symbol reimplement the same quirks that
other built in constructors do, isn't not allowing a Symbol constructor going
to avoid a lot of confusion?

For example, if you created an object using a hypothetical symbol constructor,
the symbol would be converted to a string if you tried to use it as an object
key (internally, JavaScript sees your symbol object as an object, not a
symbol), which is simply creating problems for a naive programmer.

[0] [https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/String?redirectlocale=en-
US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FString#Distinction_between_string_primitives_and_String_objects)

~~~
draw_down
The point under debate is whether it's inconsistent with Number, String, and
Boolean, which it is. I agree `new String` is not particularly useful.

~~~
thomasfoster96
Sorry, I think I misunderstood your point. I thought you meant that
inconsistency was worse than misusing constructors.

------
bpicolo
To be honest, using them to define iterators seems a bit strange, but I guess
that's the choice that's been made.

~~~
thomasfoster96
Well, it's a good compromise to avoid having a 'iterate' method on the object
prototype, which would risk name collisions, etc.

~~~
bpicolo
They could do it a'la python __iter__ or something of that nature. I think the
python strategy is a bit cleaner. (Even then __iter__ could be a keyword
meaning Symbol.iterator if that's the way to do it).

Mixing symbols in for something that seems asymptotic is the strange part.

------
iamleppert
Seems to be like another thing that will end up in my code reviews of esoteric
wind-bags.

~~~
erikpukinskis
Is it just me or is ES6 kind of ruining Javascript by adding dozens of ways of
solving problems that plain JS is perfectly capable of solving if you know how
to use it?

Should I try harder to see the usefulness of it?

Right now all it seems to have done for me is make it impossible to use NPM
modules because everything is targeting a different runtime and stuff that
expects JavaScript breaks other libraries that expect ES6 and vice versa. I'm
forced now to use what feels like a beta language in production because a
handful of key libraries now require ES6.

I am seriously considering just forking every library that ports to ES6, which
is preposterous, but I don't know what else to do. The whole point of
JavaScript in my mind was that it runs everywhere, on every obscure browser
and any machine with a node executable. ES6 has ruined what was Javascript's
most unique and most powerful feature.

~~~
iamleppert
I couldn't agree more with you. What ever happened to keeping the language
small, and allowing the community to provide for useful abstractions on top of
it?

Now we have a bloated spec. Seriously. Fat arrow syntax with explicit scope?
Bind() works just fine, thank you.

And this isn't about fear of change. Change should only be for legitimate
purpose. When I detect any trace of change for stylistic issue, I snear.

------
explorigin
I've looked at symbols before but missed the part about protocols. Thanks!

