5

In JavaScript you can compose objects using some kind of extend function.

For example I might have an observable class that exposes a set of public methods (get, push, set, increment, get, etc)

In this case the observable also happens to be an EventEmitter so it also exposes a further set of public methods (emit, on, removeListener, etc)

Both of these classes have internal underscore prefixed properties that store the state. The eventemitter uses _events to store event handlers and the observable uses _state and _id to store state and the id.

Now when I create a model using object composition like so

var Model = extend({}, Observable, {
    constructor: function () {
        // Oops, I was supposed to know Observable uses the _state name already
        this._state = { ... }
    },
    someMethod: function () { ... }
})

This causes an issue because Observable already uses the _state internal property and there is now a name clash.

I would consider it ugly to just "have to know" what objects rely on what internal properties for the mixin to safely work.

How do you avoid mixing in two objects which use the same internal property name?

Ideally this would be solved with ES6 private names, but we can't do that yet and we can't emulate them without losing performance. Unless you can provide a ES6 name emulation that does not have a large performance penalty I'm not interested in those solutions.

An alternative would be to use closures or bind but then you would be recreating the functions for every instance with is a significant performance penalty. Another alternative would be to namespace internal properties as __eventEmitter_events and __observable_state. That is just ugly and reduces to probability of a namespace clash, it doesn't remove it.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • If memory serves, ExtJS solves it in the object creation pipeline by instantiating an EventEmitter as a property hanging off the Observable, and proxying all *public* methods of the EventEmitter into the Observable using function binding, while maintaining all private state inside that EventEmitter. I'd code an example but I'm going AFK...give me an hour? – zetlen May 01 '12 at 13:09
  • @zetlen note that the proxying of all public methods using function binding means your creating a whole bunch of new functions for each observable instance. as mentioned this has the exact performance penalty as emulation of private names. This is a solution, but we want to avoid it for performance reasons – Raynos May 01 '12 at 13:12
  • I did miss that you mentioned that already, sorry! I'm not sure about your assertion that it has the "exact same" performance penalty. In all edge browsers (IE10 too) there is a native implementation of `Function.prototype.bind`. That method does return a new function, but is it as expensive as declaration? You tell me. Maybe you've already tried that! – zetlen May 01 '12 at 14:18
  • the penalty is o(n) memory instead of o(1). the other penalty is lack of extensibility – Raynos May 01 '12 at 14:30

1 Answers1

0

The trivial solution is "namespaces"

var state = "Model@v0.1.3~state";
var Model = extend({}, Observable, {
    constructor: function () {
        // Nice, I used a namespace and don't clash with "Observable@v0.2.3~state"
        this[state] = { ... }
    },
    someMethod: function () { ... }
})
Raynos
  • 166,823
  • 56
  • 351
  • 396