Патч обезьяны JavaScript новый Дата () - PullRequest
1 голос
/ 10 октября 2019

Мне нужно обезьяна исправить патч объекта даты JavaScript. Единственное, что мне нужно изменить, это new Date(), который мне нужно всегда возвращать одну и ту же дату.

Существует аналогичный вопрос об изменении даты с помощью смещения, но мне интересно, могу ли я сделать то же самое с меньшим количеством кода ?: Monkeypatch объект даты JavasScript

Изменив код из приведенного выше вопроса, у меня есть решение, которое работает с этим:

Date = (function(oldDate) {
    /**
     * @return {string}
     */
    function Date(year, month, date, hours, minutes, seconds, ms) {
      let res;
      const l = arguments.length;
      if (l == 0) {
        res = new oldDate(Date.now());
      } else if (l == 1) {
        res = new oldDate(year); // milliseconds since epoch, actually
      } else {
        res = new oldDate(
          year,
          month,
          l > 2 ? date : 1,
          l > 3 ? hours : 0,
          l > 4 ? minutes : 0,
          l > 5 ? seconds : 0,
          l > 6 ? ms : 0,
        );
      }
      if (this instanceof Date) {
        return res;
      }
      return res.toString();
    }
    Date.prototype = oldDate.prototype; // required for instanceof checks
    Date.now = function() {
      return 1570705688585; // HERE I REUTRN A FIXED DATE
    };
    Date.parse = oldDate.parse;
    Date.UTC = oldDate.UTC;
    return Date;
  })(Date, Date.now);

Глядя на эти документы: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now

Кажется, Date.now имеет поллиф, который вы можетеиспользуйте:

if (!Date.now) {
  Date.now = function now() {
    return new Date().getTime();
  };
}

Я пробовал это, но это никак не отразилось:

  Date.now = function now() {
    return 1570705688585;
  };

1 Ответ

1 голос
/ 10 октября 2019

Возможно, вы не сможете просто изменить Date.now, так как конструктор может не вызывать этот метод. Однако вы можете сделать патч короче, напрямую скопировав все свойства и переписав Date.now и конструктор с нулевым аргументом:

//keep for testing
const OriginalDateConstructor = Date;

Date = (function(oldDate) {
  function Date(...args) {
    if (args.length === 0) {
      //override the zero argument constructor
      return new oldDate(Date.now())
    } 
    
    //else delegate to the original constructor
    return new oldDate(...args);
  }
  //copy all properties from the original date, this includes the prototype
  const propertyDescriptors = Object.getOwnPropertyDescriptors(oldDate);
  Object.defineProperties(Date, propertyDescriptors);
  
  //override Date.now
  Date.now = function() {
    return 1570705688585;
  };
  
  return Date;
})(Date);

console.log("same prototype", Object.getPrototypeOf(Date) === Object.getPrototypeOf(OriginalDateConstructor))
console.log("no argument", new Date());
console.log("single argument - zero", new Date(0));
console.log("single argument - non-zero", (new Date(new OriginalDateConstructor("2019-01-01").getTime())));
console.log("passing ISO string", new Date("2019-06-01"));
console.log("passing year, month", new Date(2019, 09));
console.log("passing year, month, day", new Date(2019, 09, 15));
console.log("passing year, month, day, hour", new Date(2019, 09, 15, 10));
console.log("passing year, month, day, hour, minutes", new Date(2019, 07, 15, 10, 30));
console.log("passing year, month, day, hour, minutes, seconds", new Date(2019, 07, 15, 10, 30, 45));
console.log("passing in a date", new Date(new Date("2019-03-01")))

console.log("conversion to number", +new Date("2019-06-01T12:00"))
console.log("implicit conversion to string", "" + new Date("2019-06-01T12:00"))
...