What prevents built-in constructors from being extended?

# Axel Rauschmayer (14 years ago)

I’m still trying to understand why some of the built-in constructors can’t be extended. The following describes my current understanding. If you would, please let me know where/if I’m wrong.

  • The following built-in constructors can’t be easily extended: Array Boolean Date Function Number Object RegExp String Error and sub-constructors

  • Reason (Array): Array instances need special support to update the length property depending on what elements are added. But that specialness should go away with Allen’s proposal for overriding element access via [].

  • Reason (all): The constructors can’t be invoked as functions while handing in this – be it that they create new instances, be it that they do something else – they can’t be made to add properties to an existing instance. This prevents the pattern SuperConstructor.call(this, arg1, arg2, ...) from working.

# Lasse Reichstein (14 years ago)

On Sat, Dec 3, 2011 at 8:27 AM, Axel Rauschmayer <axel at rauschma.de> wrote:

I’m still trying to understand why some of the built-in constructors can’t be extended. The following describes my current understanding. If you would, please let me know where/if I’m wrong.

  • The following built-in constructors can’t be easily extended:    Array    Boolean    Date    Function    Number    Object    RegExp    String    Error and sub-constructors

  • Reason (Array): Array instances need special support to update the length property depending on what elements are added. But that specialness should go away with Allen’s proposal for overriding element access via [].

Arrays have a special [[Put]], but Strings have a special [[Get]] too, so Array isn't the only one with a custom internal method.

  • Reason (all): The constructors can’t be invoked as functions while handing in this – be it that they create new instances, be it that they do something else – they can’t be made to add properties to an existing instance. This prevents the pattern SuperConstructor.call(this, arg1, arg2, ...) from working.

That would be messy. If the String constructor could add "String-ness" to an existing object, what would it do to a Number object (which already have a [[PrimitiveValue]] property), or an Array (which might already have a "0" property), or a something that's already a String object, or ... the possibilities are staggering :) Would it change the [[Class]] of the obejct? It's going to be hard to make that safe.

What you need (if you need it) is a way to create a, say, Date object with a custom [[Prototype]]. That's why the common example given is Array.create - working similarly to Object.create, but creating Array objects (with class "Array" and Array behavior), just like Object.create creates Object objects. Ofcourse this needs a .create on all the special constructors.

Another option is to make a more generalized Object.createByClass("Array", proto) that creates an object with class "Array" and, since "Array" is a known class, also adds Array nature to the created object. Doing Object.createByClass("arglebargle", Object.prototype) just gets you an object where Object.prototype.toString returns "[object arglebargle]'.