ES.next private name objects provide interesting semantics, but API feels little awkward to use. With a currently proposed API it's very unlikely to become popular, although with slight adjustments it can become super tempting. While this proposal can be implemented with a private name objects, it would have much more value to be just part of it.
-
API for calling private named methods is awkward:
object[method](foo, bar)
With private name methods it's natural:
method(object, foo, bar)
-
API for accessing private names is ugly in comparison to normal properties:
var data = object[secret]
With private methods it can be more natural:
var data = secret(object)
Private methods may provide little more natural API that feels
similar to one used today. But there is much more to it, private
methods provide semantics very similar to clojure protocols
that arguably provide interesting ways to do polymorphism that
fits much better JS runtime than currently proposed classes, which
is also fully harmonious with JS prototypical inheritance. It also
solves issues inherent with diversity of community and libraries,
as on may define protocol through the set of methods that can be
independently implemented for set of libraries used. For example
event dispatching protocol may be defined via on, off, emit
private methods that later can be implemented without any conflict
risks for DOM, jQuery, Backbone, etc... This will allowing one to
use same set of privates methods regardless of which library data
structure comes from. In a way monkey patching on steroids and
conflict risks!
It may be a good idea to pass dispatch target as a this
pseudo-variable instead. This method dispatch can be used
in both in OOP and functional styles.
object[watch](observer)
watch(object, observer)
Unfortunately this will restrict "private name method" implementations to old style functions only, while a beauty of the later API is that it embraces functional nature of JS. If we had thin arrow functions this would have being more appealing:
Watchable.prototype[watch] = (watcher) -> watchable(this).push(watcher)
On the second thought though, functional invoke is in fact shorter,
than OOP method dispatch, so it may not be worth it. Also class
sugar may be adjusted such that both functional invoke and OOP
method dispatch would just work.
Update: Added support for null and undefined