Object Relay

Instead of subclassing, you can wrap an existing instance, the subject, to add validation, caching or logging. A surrogate keeps the subject's interface, a decorator adds methods, an adapter exposes a different interface, and monkey patching replaces methods on the subject itself, affecting every holder. The built-in Proxy (Proxy and Reflect) builds surrogates generically.

Surrogate, adapter and monkey patchingJavaScriptLive
class Greeter { greet() { return 'Hello'; } }
const relay = (subject) => Object.assign(Object.create(Object.getPrototypeOf(subject)), {
  greet: () => `${subject.greet()} world`,               // surrogate: same interface
});
const adapt = (subject) => ({ welcome: (who) => `${subject.greet()}, ${who}!` });  // adapter
function patch(subject) {                                // monkey patching mutates the subject
  const original = subject.greet;                        // keep it, or greet() recurses
  subject.greet = function () { return `${original.call(this)} there`; };
}
const g = new Greeter();
console.log(relay(g).greet(), relay(g) instanceof Greeter, adapt(g).welcome('Ann'));
patch(g); console.log(g.greet(), new Greeter().greet());