0

i'm trying to extend built-in JS String class using ES6 class.
I.e. just to inherit from String.

However, the code below does not work.
+= operator change myStr actual type back to String.
AFAIK, there is no operator inheritance in JS.
So, how to avoid this behaviour?

class QString extends String {
    isEmpty() {
        return this.length === 0;
    }
}

var testStr = new QString();
console.log(testStr.isEmpty());
testStr += new QString("abc");
console.log(testStr.isEmpty());  // 'TypeError: testStr.isEmpty is not a function'

P.S. I know about opportunity to add a new method String.prototype.
But this is a bad practice.

UPD: i understood what there is no + operator overloading in JS, and original answer said it clearly. However, it said nothing about inheritance and ES6 classes at all. I think at least accepted answer should be saved.

1
  • I agree with OP that this question was about following native's lead for patterns when concerned with object concatenation, something the proposed duplicate inexplicably didn't address at all. The question had little to do with operator overloading other than exemplifing the limitation encountered. Commented Oct 30, 2017 at 12:40

3 Answers 3

1

There's nothing wrong with the construction.

The issue is a misunderstanding of the ability of the "+" operator. The operator "+" in JS can only produce a string or a number, not a custom class.

Other native classes such as array have specific methods for concatenation while retaining the proto.

So you could potentially create those too.

class QString extends String {
    isEmpty() {
        return this.length === 0;
    }
    concat(){
      return new QString(this + Array.prototype.join.call(arguments, ''));
    }
}

var testQStr1 = new QString("abc");
var testQStr2 = new QString("as easy as");
var testQStr3 = new QString("123");

console.log(testQStr1);
test1 = testQStr1.concat(testQStr2,testQStr3);
console.log(test1);

At this rate though, you may as well build a simple class that accepts a string as constructor parameter and write your class without inheriting native.

Sign up to request clarification or add additional context in comments.

2 Comments

So, the short answer - "you can't do it this way". Got it. I need to know more about JS-way instead of simulating C++ STL :)
Nope. You can do it this way, but understand how combining objects in JS works. Extending native is very rare but certainly can be done. I have extended string for custom ligature handling of Arabic text for example. JS is definitely not like C++. :)
0

My guess is that you should add the method isEmpty to the String.prototype, otherwise it won't work. That's how OOJS inheritance works.

3 Comments

w3schools.com/js/js_object_prototypes.asp says (see below the page): Never modify the prototypes of standard JavaScript objects. Are you not agreed with W3C?
@eraxillan It's not w3c but w3schools, and it's infamous for being lame, so it's not a reliable source. But interestingly, w3schools is right on that, for a change.
@eraxillan The w3schools website has no affiliation with the W3C at all.
0

For some built-ins extended class instances tend to fall back to original built-in class instances. The examples include extended Promise, Number, String, because of the way how JavaScript (type conversions, await keyword, etc) works. Using extended built-in classes involves creating extended class instances at every point:

new ExtendedString(fooString + barString).extendedMethod();
ExtendedPromise.resolve(nativePromise).extendedMethod();

This is cumbersome and may defy the purpose of extending a built-in.

Since extending built-in class prototype is bad practice that is almost never justified, the right way is to not extend built-in classes but use ponyfills, which are just helper function that extend the functionality of built-in class.

For some things this approach works. For other things like checking for string length it isn't worth it, because

!str.length

takes less characters to type than

const isEmpty = require('...');
isEmpty(str);

3 Comments

I came to JS from C++, so first of all i try to imitate powerful std::string using JavaScript String inheritance. So, this is not possible in the useful way?
@eraxillan that’s a very first and usually a very bad idea to convert one programming language into another
@eraxillan Sadly, no, not really. The best thing you can do here is to make existing stuff (see the example with !str.length) work at 100% including the newer methods that can be polyfilled. And for more complex stuff ponyfills is the way to go. I guess that github.com/tc39/proposal-bind-operator was supposed to address this issue but it didn't make it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.