I've been experimenting with subclassing the built-in String object in ES2015 using Node 5.3.0. I'm running the code untranspiled using a bunch of harmony flags. Here's the full command:
node --harmony --harmony_modules --harmony_destructuring --harmony_rest_parameters --harmony_arrow_functions --harmony_spreadcalls --harmony_object --harmony_default_parameters --harmony_new_target --harmony_reflect --harmony_modules ~/t.js
Given that the spec specifically says the String object is made to be subclassable (See section 21.1.1 The String Constructor
), I'm struggling to understand if this is something that I'm doing wrong or a bug in Node or maybe even V8.
The code to reproduce the issue follows:
'use strict';
class Str extends String {
capitalize() {
return `${this.slice(0, 1).toUpperCase()}${this.slice(1)}`;
}
}
var s = new Str('asdf');
console.log(s.constructor);
//[Function: String]
console.log(s.__proto__)
//[String: '']
console.log(s.capitalize());
//TypeError: s.capitalize is not a function
The code above demonstrates that the prototype chain isn't being setup as I would expect. However, if I manually fix the __proto__
using the code below, everything works correctly.
'use strict';
class Str extends String {
constructor(...args) {
super(...args);
Object.setPrototypeOf(this, new.target.prototype);
}
capitalize() {
return `${this.slice(0, 1).toUpperCase()}${this.slice(1)}`;
}
}
var s = new Str('asdf');
console.log(s.constructor);
//[Function: Str]
console.log(s.__proto__);
//Str {}
console.log(s.capitalize());
//Asdf
I'm really curious to know why the inheritance is not working as I'd expect.
I've yet to find a definitive answer to the question, but my quick and dirty solution has been working for the moment so I'll leave it as the answer for anyone who runs into the same problem.
You can fix the prototype chain when inheriting from the String built-in using the following line in your
constructor()
:Object.setPrototypeOf(this, new.target.prototype);
The
new.target.prototype
bit ensure that should you inherit further from your own type the prototype chain will continue to be correct.