T.J. Crowder (2017-01-05T18:55:24.000Z)
tj.crowder at farsightsoftware.com (2017-01-06T10:41:28.593Z)
On Thu, Jan 5, 2017 at 5:31 PM, James Treworgy <jamietre at gmail.com> wrote: I can't address your questions about "why" (I wasn't plugged into the discussions around it), but addressing this: > This has come into play lately for me, as an DI container we use that > does exactly this doesn't work with ES6 classes (and as far as I can > tell, there's no way to make it work, other than having devs no longer > use class syntax). Can you clarify what prevents it from being made to work? I'm probably missing the point you're making there. For instance, this does some brain-dead DI (injecting an argument in the constructor) by dynamically extending the class: ```js // The class we'll do DI on class Original { constructor($foo) { this.foo = $foo; } run(num) { const result = this.foo.fooMethod(num); console.log(`num is ${num}, result is ${result}`); } } // Brain-dead di function const di = (cls, Foo) => { const o = { [cls.name]: class extends cls { constructor(...args) { super(new Foo(), ...args); } } }; return o[cls.name]; }; // Ues a class that's been DI'd const use = Original => { new Original().run(42); }; // Use it in dev use(di(Original, class Foo { fooMethod(num) { return num * 2; } })); // Use it in production use(di(Original, class Foo { fooMethod(num) { return num / 2; } })); ``` That outputs num is 42, result is 84 num is 42, result is 21 ...because of the different injected `Foo`s. (This is obviously a simplistic example.) Separately, there are some tools you can use, such as [`Reflect.construct`][1], but granted that does create an instance. For instance, if for some reason you wanted to extend a class *without* using `class`: ```js class A { amethod() { console.log("amethod"); } } function B() { const t = Reflect.construct(A, [], B); return t; } B.prototype = Object.create(A.prototype); B.prototype.constructor = B; B.prototype.bmethod = function() { console.log("bmethod"); }; const b = new B(); b.amethod(); // "amethod" b.bmethod(); // "bmethod" console.log(b instanceof A); // true console.log(b instanceof B); // true ``` Of course, that cheats a bit with that `return t;`. :-) There are probably some tools that should be added to the list. For instance, there's [this proposal][2] for `Reflect.isCallable` and `Reflect.isConstructor`). And my `bmethod` above isn't really a method, so it wouldn't be able to use `super`; in theory one could argue for a `Reflect.makeMethod` (but use cases are limited, given `class` syntax). New tools can be added if persuasive use cases come up (and people step forward to define them and get a champion on board). But circling back, I could be well wide of the mark above. If you can give us more specifics about use cases that aren't supported, we can probably do better helping with them. [1]: http://www.ecma-international.org/ecma-262/7.0/index.html#sec-reflect.construct [2]: https://github.com/caitp/TC39-Proposals/blob/master/tc39-reflect-isconstructor-iscallable.md -- T.J.