I don't think it is possible to call the constructor as a function. However, in JavaScript a class is just an object (unlike C# or Java, where it's meta data), which means that you can pass it around and dynamically extend it. E.g. you can intercept class creation like this:

function enhanceClass(c) {
    return class EnhancedClass extends c {
        constructor() {
            //do your magic here
        }
    }
}

class MyClass {}

const EnhancedMyClass = enhanceClass(MyClass);
new EnhancedMyClass();

As for `toString` & not being able to call a function directly: `toString` is already overwriteable, and in ES5 code it wasn't uncommon to throw from a constructor if it wasn't called as one (for good reasons). ES6 classes just do that for you.

On 01/05/2017 06:31 PM, James Treworgy wrote:
Hi - I am brand new to this list, I find myself here because of a confounding issue related to ES6 classes vs. traditional constructors. Forgive me if this is something that's been hashed out in times past. I looked around for discussion online and couldn't find anything more than the observation that the spec prohibits invoking it - not really any discussion. Probably a failing of google more than anything else, so if there's some discussion that I should read to catch up please point me there.

Here's my issue. The ES6 spec prohibits invoking class constructors without "new". This makes such functions a special case, e.g.

class Test() {}

// typeof Test === 'function'  // yep
// Test.prototype.constructor === Test // yep

// Test() => nope ... TypeError: Class constructor Test cannot be invoked without 'new'
// Test.call() ... nope
// Test.apply() ... nope

This has some interesting consequences. It means testing something for typeof "function" no longer guarantees it can be invoked without error. Also "function.toString()" can now return something that isn't actually a legal function definiton (since it returns the whole class as text). There seems to be no method, through various javascript reflection/invocation techniques or otherwise, to invoke a class constructor except by creating an instance of the class.

For tool-builders the consequences of this are significant. It's no longer possible to create something that can extend/wrap/act on a prototype by intercepting it's construction process, as it was before with plain ES5 constructors. So classes are fundamentally different than prototype contructors in how we can use them, far more than syntactic sugar. 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).

This seems a strange design decision. Even conventional OO languages like C# have the capability to reflect on classes and access the constructor directly as a function. It seems to fly in the face of the basic openness/dyanamic nature of JavaScript, and more signficantly, creates a kind of backward incompatibility since a function is no longer just a function.

I'm wondering whether I'm missing some mechanism for legally accessing a class constructor as a function (other than parsing the output of toString() and eval!) -- and generally thoughts on this aspect of the ES6 specification.

Thank you!



_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to