Why is Google Closure Compiler failing on my ES6 o

2019-05-05 06:31发布

问题:

Please note: this question relates to the use of Google's Closure Compiler. It's not directly about ES6, since that part is working.

I've written a class in ES6 which extends the native Date object. It's a large class, but this is a simplified version:

   class Dative extends Date {

       constructor (dateData) {
           super();
           super.setTime(Date.parse(dateData));
       }


       addMilliseconds (ms) {
           super.setTime(super.getTime() + ms);
       }

   }

The code above works fine in Chrome and Firefox. However, when I pass it through Closure Compiler, it throws errors:

Uncaught TypeError: Method Date.prototype.setTime called on
incompatible receiver [object Object]

Update: calling native Date methods also fails in the compiled version but works fine uncompiled, with a message saying this is not a Date object.

What I don't understand is why code that works in its original form breaks when it's been compiled.

Am I doing something wrong, or is this a compiler bug?

I'm using the latest version of compiler.jar. For reference, this is what closure compiler produces:

var $jscomp = {
    scope: {},
    inherits: function(a, b) {
        function d() {}
        d.prototype = b.prototype;
        a.prototype = new d;
        a.prototype.constructor = a;
        for (var c in b)
            if (Object.defineProperties) {
                var e = Object.getOwnPropertyDescriptor(b, c);
                e && Object.defineProperty(a, c, e)
            } else
                a[c] = b[c]
    }
}
  , Dative = function(a) {
    Date.call(this);
    Date.prototype.setTime.call(this, Date.parse(a))
};

$jscomp.inherits(Dative, Date);
Dative.UTC = Date.UTC;
Dative.parse = Date.parse;
Dative.now = Date.now;
Dative.prototype.addMilliseconds = function(a) {
    Date.prototype.setTime.call(this, Date.prototype.getTime.call(this) + a)
};
//# sourceMappingURL=./DativeShort.map

回答1:

Date is not subclassable in ES5. So what you want is not possible in ES5 environments in the first place.

The transpiled code cannot work in ES6 environments either. From the specification

The Date constructor is designed to be subclassable. It may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Date behaviour must include a super call to the Date constructor to create and initialize the subclass instance with a [[DateValue]] internal slot.

Without calling super it won't work. Date.call(this); doesn't do the trick. Basically, if you transpile code to ES5, subclassing built-in types is a no-go.

So no, it's not a problem of Google Closure.