Make an object's methods chainable so calls can be written in a fluent sequence
Implement a small StringBuilder so its mutating methods can be chained: new StringBuilder().append('a').append('b').upper().value should yield 'AB'. Provide append(s) and upper() as chainable methods and a value accessor returning the built string.
class StringBuilder {
constructor() {
this.str = '';
}
append(s) {
// your code here
}
upper() {
// your code here
}
get value() {
return this.str;
}
}
Write the implementation.
Each mutating method updates the instance state and then return this. Returning the same object lets the next call in the chain operate on it, so append('a').append('b').upper() reads as one fluent sequence. The terminal value getter returns the actual result, since it ends the chain — exactly how jQuery achieves fluent APIs.
- ✗Returning the mutated field (
this.str) instead ofthis, which breaks the next method call - ✗Returning nothing (
undefined), so the second method in the chain throws - ✗Mutating in
appendbut forgettingupper()must alsoreturn thisto stay chainable
- →Why must a chainable method return
thisrather than the updated value? - →How would a non-chainable terminal method like
valuediffer from the chainable ones?
Solution
Each mutating method changes the state and returns this.
class StringBuilder {
constructor() {
this.str = '';
}
append(s) {
this.str += s;
return this;
}
upper() {
this.str = this.str.toUpperCase();
return this;
}
get value() {
return this.str;
}
}
new StringBuilder().append('a').append('b').upper().value; // 'AB'
How it works
The fluent API rests on one rule: a mutating method returns this — the same instance. The next call in the chain runs on that same object, so append('a').append('b').upper() accumulates changes in one StringBuilder.
The value getter ends the chain: it returns the built string, not the object, so it goes last. If a mutating method returned this.str, the next .append would be looked up on the string rather than the builder, and the chain would break. </content>