Ωmega
Ωmega

Reputation: 43683

How to call original method after its override

In Javascript, when I override Date.prototype.toString function, the output of the Date() function is not affected and the function keeps its original code.

console.log(Date());
console.log(new Date().toString());

Date.prototype.toString = function() { return this.toISOString() }

console.log(Date());
console.log(new Date().toString());

"Tue Jan 26 2021 17:30:33 GMT-0500 (Eastern Standard Time)"

"Tue Jan 26 2021 17:30:33 GMT-0500 (Eastern Standard Time)"

"Tue Jan 26 2021 17:30:33 GMT-0500 (Eastern Standard Time)"

"2021-01-26T22:30:33.821Z"

Test it here.


However, when I needed to use a more complex override of the Date class - in my case changing the clock step to 5-second interval - after I override Date.prototype.toString function, the output of the Date() changes as well. Since the functionality of the Date() function should not change, this is an unwanted and unwelcome change.

console.log(Date());
console.log(new Date().toString());

(function() {
  let ___now = Date.now;
  Date = new Proxy(Date, {
    construct(target, args) {
      if (args[0] === undefined) args[0] = this.adjust()
      let date = new target(...args);
      return date;
    },
    apply(target, thisArg, argumentList) {
      return new Date(this.adjust()).toString();
    },
    adjust() {
      return 5000 * Math.floor(___now() / 5000);
    }
  });
})();
Date.prototype.toString = function() { return this.toISOString() }

console.log(Date());
console.log(new Date().toString());

"Tue Jan 26 2021 17:30:35 GMT-0500 (Eastern Standard Time)"

"Tue Jan 26 2021 17:30:35 GMT-0500 (Eastern Standard Time)"

"2021-01-26T22:30:35.000Z" "2021-01-26T22:30:35.000Z"

"2021-01-26T22:30:35.000Z" "2021-01-26T22:30:35.000Z"

Test it here.


How should I modify the code above to force Date() function to use the original toString() function, even when it is overridden? The change of toString() should be applicable only when it is called explicitly, as shown in the examples above.

Upvotes: 3

Views: 120

Answers (1)

smac89
smac89

Reputation: 43206

The following should work for you:

console.log(Date());
console.log(new Date().toString());

(function() {
  const ___now = Date.now;
  const ___toString = Date.prototype.toString;
  Date = new Proxy(Date, {
    construct(target, args) {
      if (args[0] === undefined) args[0] = this.adjust()
      let date = new target(...args);
      return date;
    },
    apply(target, thisArg, argumentList) {
      return ___toString.bind(new Date()).call();
    },
    adjust() {
      return 5000 * Math.floor(___now() / 5000);
    }
  });
})();

Date.prototype.toString = function() { return this.toISOString() }

console.log(Date());
console.log(new Date().toString());

Upvotes: 3

Related Questions