首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何扩展Javascript Date对象?

如何扩展Javascript Date对象?
EN

Stack Overflow用户
提问于 2011-05-21 00:56:20
回答 9查看 18.7K关注 0票数 24

我正在尝试子类化/扩展原生Date对象,而不修改原生对象本身。

我试过了:

代码语言:javascript
复制
    var util = require('util');

    function MyDate() {
        Date.call(this);
    }
    util.inherits(MyDate, Date);

    MyDate.prototype.doSomething = function() {
        console.log('Doing something...');
    };        

    var date = new MyDate();
    date.doSomething();

    console.log(date);
    console.log(date.getHours());

还有这个:

代码语言:javascript
复制
function MyDate() {

    }

    MyDate.prototype = new Date();

    MyDate.prototype.doSomething = function() {
        console.log("DO");
    }

    var date = new MyDate();
    date.doSomething();
    console.log(date);

在这两种情况下,date.doSomething()都可以工作,但当我调用任何本机方法(如date.getHours()甚至console.log(date) )时,都会得到“TypeError: this is not a Date object.‘”。

有什么想法吗?或者我坚持扩展顶级Date对象?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-05-21 01:11:50

查看date.js中的v8代码:

代码语言:javascript
复制
function DateGetHours() {
  var t = DATE_VALUE(this);
  if (NUMBER_IS_NAN(t)) return t;
  return HOUR_FROM_TIME(LocalTimeNoCheck(t));
}

看起来DATE_VALUE是一个完成这项任务的宏:

代码语言:javascript
复制
DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_ValueOf(arg) : ThrowDateTypeError());

所以,看起来v8不会让你子类Date。

票数 19
EN

Stack Overflow用户

发布于 2015-06-17 12:36:23

这可以在ES5中完成。它需要直接修改原型链。这是使用__proto__Object.setPrototypeOf()完成的。我在示例代码中使用__proto__,因为它得到了最广泛的支持(尽管标准是Object.setPrototypeOf)。

代码语言:javascript
复制
function XDate(a, b, c, d, e, f, g) {
  var x;
  switch (arguments.length) {
    case 0:
      x = new Date();
      break;
    case 1:
      x = new Date(a);
      break;
    case 2:
      x = new Date(a, b);
      break;
    case 3:
      x = new Date(a, b, c);
      break;
    case 4:
      x = new Date(a, b, c, d);
      break;
    case 5:
      x = new Date(a, b, c, d, e);
      break;
    case 6:
      x = new Date(a, b, c, d, e, f);
      break;
    default:
      x = new Date(a, b, c, d, e, f, g);
  }
  x.__proto__ = XDate.prototype;
  return x;
}

XDate.prototype.__proto__ = Date.prototype;

XDate.prototype.foo = function() {
  return 'bar';
};

诀窍在于,我们实际上实例化了一个Date对象(使用正确数量的参数),这将为我们提供一个内部[[Class]]设置正确的对象。然后我们修改它的原型链,使其成为XDate的实例。

因此,我们可以通过执行以下操作来验证所有这些:

代码语言:javascript
复制
var date = new XDate(2015, 5, 18)
console.log(date instanceof Date) //true
console.log(date instanceof XDate) //true
console.log(Object.prototype.toString.call(date)) //[object Date]
console.log(date.foo()) //bar
console.log('' + date) //Thu Jun 18 2015 00:00:00 GMT-0700 (PDT)

据我所知,这是唯一一种将date子类化的方法,因为Date()构造函数会变魔术来设置内部[[Class]],而大多数date方法都需要设置它。这将在Node、IE 9+和几乎所有其他JS引擎中工作。

类似的方法也可以用于对Array进行子类化。

票数 9
EN

Stack Overflow用户

发布于 2015-04-15 23:22:13

在ES6中,可以子类化内置构造函数(ArrayDateError) - reference

问题是没有办法做到这一点与目前的ES5引擎,因为巴别塔indicates,将需要一个浏览器与原生ES6支持。

到目前为止(2015-04-15),当前用于子类化的ES6 browser support非常弱/不存在。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6075231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档