网站搜索

javascript - 使用 TypeScript 扩展 JS Date,但 "this" 关键字无法正常工作


在使用下面的代码扩展 JavaScript 的 Date 类型时,当调用新函数时会抛出错误,因为 this 关键字未正确引用,即当我调用 addHours 函数时,我得到的错误是:

未捕获的类型错误:_this.getTime 不是一个函数

当我调试时,我看到“this”的类型是“对象 Window”

这是我正在使用的 TypeScript 代码:

declare interface Date {
    stdTimezoneOffset: () => number;
    dst: () => boolean;
    addHours: (h: number) => void;
    test: () => void;
}

Date.prototype.stdTimezoneOffset = () => {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
};

Date.prototype.dst = () => {
    return this.getTimezoneOffset() < this.stdTimezoneOffset();
};

Date.prototype.addHours = (h: number) => {
    this.setTime(this.getTime() + (h * 60 * 60 * 1000));
};

并且创建的 .JS 文件是这个:

var _this = this;
Date.prototype.stdTimezoneOffset = function () {
    var jan = new Date(_this.getFullYear(), 0, 1);
    var jul = new Date(_this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
};
Date.prototype.dst = function () {
    return _this.getTimezoneOffset() < _this.stdTimezoneOffset();
};
Date.prototype.addHours = function (h) {
    _this.setTime(_this.getTime() + (h * 60 * 60 * 1000));
};
Date.prototype.test = function () {
    return +_this.getTime();
};

现在在我看来,问题出在 .JS 文件的第一行:

var _this = this;

但我不知道该怎么修理它。

答案#1

你正在使用箭头函数。箭头函数会闭包其定义处的 this,而不是由它们的调用方式来设置 this;后者对于原型函数很重要。

改用普通函数:

Date.prototype.stdTimezoneOffset = function() {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
};

附注:在增强内置原型时,使用 defineProperty 或 defineProperties 创建 不可枚举的属性是一个非常好的做法。所以:

Object.defineProperties(Date.prototype, {
    stdTimezoneOffset: {
        value: function () {
            var jan = new Date(this.getFullYear(), 0, 1);
            var jul = new Date(this.getFullYear(), 6, 1);
            return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
        },
        configurable: true,
        writable: true
    },
    dst: {
        value: function() {
            return this.getTimezoneOffset() < this.stdTimezoneOffset();
        },
        configurable: true,
        writable: true
    },
    addHours: {
        value: function(h: number) {
            this.setTime(this.getTime() + (h * 60 * 60 * 1000));
        },
        configurable: true,
        writable: true
    }
});

(configurable: true, writable: true 只是因为这是 Date.prototype 上内置属性的默认值,所以我与它们保持一致。)