B
B
Bogdan2018-03-11 15:56:05
JavaScript
Bogdan, 2018-03-11 15:56:05

Date inheritance?

Hello, tell me please.
When I create my class and inherit with new syntax then everything works

class SpaceDate extends Date { }

let dateOriginal = new SpaceDate(2017, 1, 22);
console.log( dateOriginal.getDay() ); // 3
console.log( dateOriginal instanceof SpaceDate); // true

But if I create through the class constructor, then the error
const SpaceDate = function( ...args ) {
    Date.call( this, ...args );
  }

  SpaceDate.prototype = Object.create( Date.prototype )
  SpaceDate.prototype.constructor = SpaceDate;

let dateOriginal = new SpaceDate(2017, 1, 22);
console.log( dateOriginal instanceof SpaceDate);
console.log( dateOriginal.getDay() );

Uncaught TypeError: this is not a Date object.

Class is a semantic sugar over the class constructor and prototype, so why, then, can't you create it through the class constructor? Thank you.
Even after transpiling Babel error
spoiler
"use strict";

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError(
      "this hasn't been initialised - super() hasn't been called"
    );
  }
  return call && (typeof call === "object" || typeof call === "function")
    ? call
    : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError(
      "Super expression must either be null or a function, not " +
        typeof superClass
    );
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass)
    Object.setPrototypeOf
      ? Object.setPrototypeOf(subClass, superClass)
      : (subClass.__proto__ = superClass);
}

var SpaceDate = (function(_Date) {
  _inherits(SpaceDate, _Date);

  function SpaceDate() {
    _classCallCheck(this, SpaceDate);

    return _possibleConstructorReturn(
      this,
      (SpaceDate.__proto__ || Object.getPrototypeOf(SpaceDate))
        .apply(this, arguments)
    );
  }

  return SpaceDate;
})(Date);

var dateOriginal = new SpaceDate(2017, 1, 22);
console.log(dateOriginal instanceof SpaceDate);
console.log(dateOriginal.getDay());

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2018-03-11
@bogdan_uman

The problem is that in the methods of the Date prototype there is a check that a date instance has been passed. Moreover, the verification does not go along the chain of prototypes.
Old V8 source code :

function DateGetTime() {
  CHECK_DATE(this);
  return UTC_DATE_VALUE(this);
}

Someone wrote that CHECK_DATE has the following implementation:
However, it's all rewritten in C++ now .
If you look at the specification , you can see that the prototype methods call native functions that perform all the calculations, and here it is important that they are given a valid date object. Therefore, apparently, there is a strict check.
A solution to this problem is to change the prototype chain of the instance:
function SpaceDate(...args) {
  var date;
  date = new Date(...args);
  date.__proto__ = SpaceDate.prototype;
  return date;
}

SpaceDate.prototype.__proto__ = Date.prototype;

SpaceDate.prototype.test = function() {
  return this;
};

The returned object will be a Date , and the prototype chain will be with your methods. The prototype of the original Date object is not affected in any way.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question