Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I extend (with a new name) a static function in javascript without affecting the original?

I'm having trouble working out how to extend a static function (momentjs) so that I can override the methods, but without altering the original function.

To be clear I know how to extend an instance of moment to override the functions, but I want to extend the library directly so I get my own named instance of moment that I can use in the same way as momentjs.

As an example, I'd like to be able to do the following

extendedMoment().customFunction() //do something custom
extendedMoment().toString() //use customised toString() method
extendedMoment().format() //use the original momentjs method

I've tried a few options with copying the prototype etc, but editing the prototype of the new extendedMoment function seems to affect the original.

Update: answered below by @PatrickRoberts

like image 784
Zak Henry Avatar asked Sep 26 '22 18:09

Zak Henry


1 Answers

After some digging into the source, you can't really directly extend the library because there are several scoped functions which are not exposed, and moment() is actually a wrapper of a wrapper of a wrapper of a wrapper of the constructor. So here's about the best you can do by reusing the same extended prototype rather than assigning scoped functions inside the factory extension:

function extendedMoment () {
  return Object.setPrototypeOf(moment(), extendedMoment.prototype);
}

Object.setPrototypeOf(extendedMoment.prototype, moment.prototype);
Object.setPrototypeOf(extendedMoment, moment);

extendedMoment.prototype.toString = function toString () {
  return this.format('YYYY-MM-DD');
};

console.log("Original: " + moment().toString());
console.log("Extended: " + extendedMoment().toString());
<script src="http://momentjs.com/downloads/moment.min.js"></script>

The way this works is it replaces the instance's prototype (which is initially Moment.prototype) with extendedMoment.prototype inside the factory extension, reusing the same toString function for all instances of extendedMoment.

EDIT

I caught myself using the term "constructor" for extendedMoment so I corrected myself. It is actually a factory extension, since it is a static function as @ZakHenry pointed out. Apologies for the misnomer.

like image 140
Patrick Roberts Avatar answered Oct 12 '22 23:10

Patrick Roberts