Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript:重写Date.prototype.constructor_Javascript_Date_Constructor_Prototype - Fatal编程技术网

JavaScript:重写Date.prototype.constructor

JavaScript:重写Date.prototype.constructor,javascript,date,constructor,prototype,Javascript,Date,Constructor,Prototype,我想更改标准日期对象的行为。传递给构造函数的0..99之间的年份应解释为fullYear(没有添加1900)。但是我下面的函数不起作用 var oDateConst = Date.prototype.constructor; // save old contructor Date.prototype.constructor = function () { var d = oDateConst.apply(oDateConst, arguments); // create object

我想更改标准日期对象的行为。传递给构造函数的
0..99
之间的年份应解释为
fullYear
(没有添加
1900
)。但是我下面的函数不起作用

var oDateConst = Date.prototype.constructor; // save old contructor

Date.prototype.constructor = function () {
    var d = oDateConst.apply(oDateConst, arguments); // create object with it
    if ( ((arguments.length == 3) || (arguments.length == 6))
        && ((arguments[0] < 100) && (arguments[0] >= 0))) {
        d.setFullYear(arguments[0]);
    }
    return d;
}
var oDateConst=Date.prototype.constructor;//拯救老承包商
Date.prototype.constructor=函数(){
var d=oDateConst.apply(oDateConst,参数);//使用它创建对象
if(((arguments.length==3)| |(arguments.length==6))
&&((参数[0]<100)和&(参数[0]>=0))){
d、 setFullYear(参数[0]);
}
返回d;
}

为什么从来没有人打过电话?您将如何解决此问题?

它从未被调用的原因是您在
Date.prototype
上更改了
constructor
属性。但是,您可能仍在使用代码
newdate()
创建日期。所以它从不使用构造函数。您真正想做的是创建自己的日期构造函数:

function MyDate() {
    var d = Date.apply(Date, arguments);
    if ((arguments.length == 3 || arguments.length == 6)
        && (arguments[0] < 100 && arguments[0] >= 0)) {
        d.setFullYear(arguments[0]);
    return d;
}
function myDate() {
    var date = instantiate(Date, arguments);
    var args = arguments.length;
    var arg = arguments[0];

    if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
        date.setFullYear(arg);
    return date;
}
编辑:而不是使用
Date.apply
我宁愿使用以下
实例化
函数,该函数允许您:

以下是我将如何实现新的日期构造函数:

function MyDate() {
    var d = Date.apply(Date, arguments);
    if ((arguments.length == 3 || arguments.length == 6)
        && (arguments[0] < 100 && arguments[0] >= 0)) {
        d.setFullYear(arguments[0]);
    return d;
}
function myDate() {
    var date = instantiate(Date, arguments);
    var args = arguments.length;
    var arg = arguments[0];

    if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
        date.setFullYear(arg);
    return date;
}
函数myDate(){
变量日期=实例化(日期、参数);
var args=arguments.length;
var arg=参数[0];
如果((args==3 | | args==6)和&arg<100&&arg>=0)
日期。设置完整年份(arg);
返回日期;
}
编辑:如果要覆盖本机日期构造函数,则必须执行以下操作:

var d = MyDate();
Date = function (Date) {
    MyDate.prototype = Date.prototype;

    return MyDate;

    function MyDate() {
        var date = instantiate(Date, arguments);
        var args = arguments.length;
        var arg = arguments[0];

        if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
            date.setFullYear(arg);
        return date;
    }
}(Date);
Date=函数(日期){
MyDate.prototype=Date.prototype;
返回MyDate;
函数MyDate(){
变量日期=实例化(日期、参数);
var args=arguments.length;
var arg=参数[0];
如果((args==3 | | args==6)和&arg<100&&arg>=0)
日期。设置完整年份(arg);
返回日期;
}
}(日期);

借助Aadit M Shah的原生日期构造函数重写-这应该是一个回答,但我没有足够的SO rep来实现-正如@sakthi提到的,这样做会丢失原生日期方法。这有点糟糕,因为Date方法是不可枚举的,所以您必须对它们进行一些修改才能克隆它们

首先,我建议不要这样做,除非你必须这样做。在我的例子中,我在一个应用程序中使用了一堆遗留代码,这些代码使用格式“m-d-yyyy”构建日期,该格式在chrome中有效,但在safari中无效。我不能只在应用程序中进行查找/替换,因为有很多实例是从服务层或数据库中提取日期字符串的。因此,我决定在有“m-d-yyy”格式的datestring参数的情况下重写日期构造函数。我希望它尽可能的微创,这样它就可以作为一个正常的约会

这里是我的更改-它应该允许您通过对构造函数的一些更改来覆盖date,但其他所有更改都是相同的。您需要在调用instantiate以执行您希望构造函数处理的任何操作之前更改MyDate构造函数。这将在应用系统日期构造函数之前发生

var bind = Function.bind;
var unbind = bind.bind(bind);

function instantiate(constructor, args) {
    return new (unbind(constructor, null).apply(null, args));
}

Date = function (Date) {

    // copy date methods - this is a pain in the butt because they're mostly nonenumerable
    // Get all own props, even nonenumerable ones
    var names = Object.getOwnPropertyNames(Date);
    // Loop through them
    for (var i = 0; i < names.length; i++) {
        // Skip props already in the MyDate object
        if (names[i] in MyDate) continue;
        // Get property description from o
        var desc = Object.getOwnPropertyDescriptor(Date, names[i]);
        // Use it to create property on MyDate
        Object.defineProperty(MyDate, names[i], desc);
    }

    return MyDate;

    function MyDate() {
        // we only care about modifying the constructor if a datestring is passed in
        if (arguments.length === 1 && typeof (arguments[0]) === 'string') {
            // if you're adding other date transformations, add them here

            // match dates of format m-d-yyyy and convert them to cross-browser-friendly m/d/yyyy
            var mdyyyyDashRegex = /(\d{1,2})-(\d{1,2})-(\d{4})/g;
            arguments[0] = arguments[0].replace(mdyyyyDashRegex, function (match, p1, p2, p3) {
                return p1 + "/" + p2 + "/" + p3;
            });
        }

        // call the original Date constructor with whatever arguments are passed in here
        var date = instantiate(Date, arguments);

        return date;
    }
}(Date);
var bind=Function.bind;
var unbind=bind.bind(bind);
函数实例化(构造函数、参数){
返回new(取消绑定(构造函数,null).apply(null,args));
}
日期=功能(日期){
//复制日期方法-这是一个痛苦的屁股,因为它们大多是不可数的
//拥有所有自己的道具,即使是不可计算的道具
var name=Object.getOwnPropertyNames(日期);
//循环通过它们
对于(var i=0;i
参考资料:

  • (本帖)

关于Matthew Albert的帖子中提到的技术,除了Dan Hlavenka发布的观点外,还有一个测试场景失败。请参阅以下代码:

typeof Date() == typeof new Date()     //Should be false, but it returns true

在遗留项目中,上述场景可能会打破一些场景。除了上述内容和Dan Hlavenka指出的内容外,我同意这是迄今为止最完整的解决方案。

这里是一个非常灵活的解决方案。它(我相信)处理所有不同的情况

DateStub-允许删除日期函数。
如果你有 '新日期(…)…'散布在你的代码中, 你想测试它,这是给你的。 它也适用于“时刻”

/**
 * DateStub - Allows for stubbing out the Date function.  If you have
 *      'new Date(...)....' sprinkled throughout your code,
 *      and you want to test it, this is for you.
 *
 * @param {string} arguments Provide 0 to any number of dates in string format.
 *
 * @return a date object corresponding to the arguments passed in.
 *      If you pass only one date in, this will be used by all 'new Date()' calls.
 *      This also provides support for 'Date.UTC()', 'Date.now()', 'Date.parse()'.
 *      Also, this works with the moments library.
 *
 * Examples:
    {   // Test with 1 argument
        Date = DateStub('1/2/2033');        // Override 'Date'

        expect(new Date().toString())
            .toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');
        expect(new Date().toString())
            .toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');

        Date = DateStub.JavaScriptDate;     // Reset 'Date'
    }
    {   // Call subsequent arguments, each time 'new Date()' is called
        Date = DateStub('1/2/1111', '1/2/1222'
                        , '1/2/3333', '1/2/4444');  // Override 'Date'

        expect(new Date().toString())
            .toEqual('Mon Jan 02 1111 00:00:00 GMT-0500 (EST)');
        expect(new Date().toString())
            .toEqual('Sun Jan 02 1222 00:00:00 GMT-0500 (EST)');
        expect(new Date().toString())
            .toEqual('Fri Jan 02 3333 00:00:00 GMT-0500 (EST)');
        expect(new Date().toString())
            .toEqual('Sat Jan 02 4444 00:00:00 GMT-0500 (EST)');

        Date = DateStub.JavaScriptDate;     // Reset 'Date'
    }
    {   // Test 'Date.now()'.  You can also use: 'Date.UTC()', 'Date.parse()'
        Date = DateStub('1/2/2033');

        expect(new Date(Date.now()).toString())
                .toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');

        Date = DateStub.JavaScriptDate;     // Reset 'Date'
    }
 *
 * For more info:  AAkcasu@gmail.com
 */

const DateStub =
    function () {
        function CustomDate(date) {
            if (!!date) { return new DateStub.JavaScriptDate(date); }
            return getNextDate();
        };
        function getNextDate() {
            return dates[index >= length ? index - 1 : index++];
        };

        if (Date.name === 'Date') {
            DateStub.prototype = Date.prototype;
            DateStub.JavaScriptDate = Date;

            // Add Date.* methods.
            CustomDate.UTC = Date.UTC;
            CustomDate.parse = Date.parse;
            CustomDate.now = getNextDate;
        }

        var dateArguments = (arguments.length === 0)
            ? [(new DateStub.JavaScriptDate()).toString()] : arguments
            , length = dateArguments.length
            , index = 0
            , dates = [];
        for (var i = 0; i < length; i++) {
            dates.push(new DateStub.JavaScriptDate(dateArguments[i]));
        }

        return CustomDate;
    };

module.exports = DateStub;

// If you have a test file, and are using node:
// Add this to the top:  const DateStub = require('./DateStub');


/**
*DateStub-允许删除日期函数。如果你有
*“新日期(…)…”散布在您的代码中,
*你想测试它,这是给你的。
*
*@param{string}参数以字符串格式提供0到任意数量的日期。
*
*@返回日期对象