通过调用prototype.constructor.apply 实例化一个JavaScript 对象 [英] Instantiating a JavaScript object by calling prototype.constructor.apply

查看:21
本文介绍了通过调用prototype.constructor.apply 实例化一个JavaScript 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我从我正在尝试做的事情的具体例子开始.

Let me start with a specific example of what I'm trying to do.

我有一个格式为 [ 2008, 10, 8, 00, 16, 34, 254 ] 的年、月、日、小时、分钟、秒和毫秒组件数组.我想使用以下标准构造函数实例化 Date 对象:

I have an array of year, month, day, hour, minute, second and millisecond components in the form [ 2008, 10, 8, 00, 16, 34, 254 ]. I'd like to instantiate a Date object using the following standard constructor:

new Date(year, month, date [, hour, minute, second, millisecond ])

如何将数组传递给此构造函数以获取新的 Date 实例?[ 更新:我的问题实际上超出了这个具体例子.我想要一个通用的解决方案,用于内置 JavaScript 类,如 Date、Array、RegExp 等,它们的构造函数超出了我的能力范围.]

How can I pass my array to this constructor to get a new Date instance? [ Update: My question actually extends beyond this specific example. I'd like a general solution for built-in JavaScript classes like Date, Array, RegExp, etc. whose constructors are beyond my reach. ]

我正在尝试执行以下操作:

I'm trying to do something like the following:

var comps = [ 2008, 10, 8, 00, 16, 34, 254 ];
var d = Date.prototype.constructor.apply(this, comps);

我可能在某处需要一个new".上面只是返回当前时间,就像我调用了(new Date()).toString()"一样.我也承认我可能完全在上面的错误方向:)

I probably need a "new" in there somewhere. The above just returns the current time as if I had called "(new Date()).toString()". I also acknowledge that I may be completely in the wrong direction with the above :)

注意:请不要使用 eval() 也不要访问数组项.我很确定我应该能够按原样使用该数组.

Note: No eval() and no accessing the array items one by one, please. I'm pretty sure I should be able to use the array as is.

由于还没有人能够提出有效的答案,我已经做了更多的尝试.这是一个新发现.

Since no one has been able to come up with a working answer yet, I've done more playing around. Here's a new discovery.

我可以用自己的班级做到这一点:

I can do this with my own class:

function Foo(a, b) {
    this.a = a;
    this.b = b;

    this.toString = function () {
        return this.a + this.b;
    };
}

var foo = new Foo(1, 2);
Foo.prototype.constructor.apply(foo, [4, 8]);
document.write(foo); // Returns 12 -- yay!

但它不适用于内在的 Date 类:

But it doesn't work with the intrinsic Date class:

var d = new Date();
Date.prototype.constructor.call(d, 1000);
document.write(d); // Still returns current time :(

它也不适用于 Number:

Neither does it work with Number:

var n = new Number(42);
Number.prototype.constructor.call(n, 666);
document.write(n); // Returns 42

也许这对于内在对象是不可能的?顺便说一句,我正在使用 Firefox 进行测试.

Maybe this just isn't possible with intrinsic objects? I'm testing with Firefox BTW.

推荐答案

我自己做了更多调查,得出的结论是这是不可能的壮举,因为日期类已实现.

I've done more investigation of my own and came up with the conclusion that this is an impossible feat, due to how the Date class is implemented.

我检查了 SpiderMonkey 源代码以了解 Date 是如何实现的.我认为这一切都归结为以下几行:

I've inspected the SpiderMonkey source code to see how Date was implemented. I think it all boils down to the following few lines:

static JSBool
Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble *date;
    JSString *str;
    jsdouble d;

    /* Date called as function. */
    if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
        int64 us, ms, us2ms;
        jsdouble msec_time;

        /* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS',
         * so compute ms from PRMJ_Now.
         */
        us = PRMJ_Now();
        JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
        JSLL_DIV(ms, us, us2ms);
        JSLL_L2D(msec_time, ms);

        return date_format(cx, msec_time, FORMATSPEC_FULL, rval);
    }

    /* Date called as constructor. */
    // ... (from here on it checks the arg count to decide how to create the date)

当 Date 用作函数时(无论是作为 Date() 还是 Date.prototype.constructor(),它们都是一样的),它默认为将当前时间作为语言环境格式的字符串返回.这与传入的任何参数无关:

When Date is used as a function (either as Date() or Date.prototype.constructor(), which are exactly the same thing), it defaults to returning the current time as a string in the locale format. This is regardless of any arguments that are passed in:

alert(Date()); // Returns "Thu Oct 09 2008 23:15:54 ..."
alert(typeof Date()); // Returns "string"

alert(Date(42)); // Same thing, "Thu Oct 09 2008 23:15:54 ..."
alert(Date(2008, 10, 10)); // Ditto
alert(Date(null)); // Just doesn't care

我不认为在 JS 级别可以做任何事情来规避这一点.而这大概就是我对这个话题的追求了.

I don't think there's anything that can be done at the JS level to circumvent this. And this is probably the end of my pursuit in this topic.

我还注意到一些有趣的事情:

I've also noticed something interesting:

    /* Set the value of the Date.prototype date to NaN */
    proto_date = date_constructor(cx, proto);
    if (!proto_date)
        return NULL;
    *proto_date = *cx->runtime->jsNaN;

Date.prototype 是一个内部值为 NaN 的 Date 实例,因此,

Date.prototype is a Date instance with the internal value of NaN and therefore,

alert(Date.prototype); // Always returns "Invalid Date"
                       // on Firefox, Opera, Safari, Chrome
                       // but not Internet Explorer

IE 没有让我们失望.它做的事情有点不同,可能将内部值设置为 -1 以便 Date.prototype 总是返回一个稍早于纪元的日期.

IE doesn't disappoint us. It does things a bit differently and probably sets the internal value to -1 so that Date.prototype always returns a date slightly before epoch.

我终于深入研究了 ECMA-262 本身,结果证明,我想要实现的(使用 Date 对象)是——根据定义——不可能:

I've finally dug into ECMA-262 itself and it turns out, what I'm trying to achieve (with the Date object) is -- by definition -- not possible:

15.9.2 作为函数调用的日期构造函数

当 Date 被称为函数而不是构造函数,它返回一个字符串表示当前时间(UTC).

When Date is called as a function rather than as a constructor, it returns a string representing the current time (UTC).

注意 函数call Date(…) 不等同于对象创建表达式 new Date(…)具有相同的论点.

NOTE The function call Date(…) is not equivalent to the object creation expression new Date(…) with the same arguments.

15.9.2.1 日期 ( [ 年 [, 月 [, 日期 [, 小时 [, 分钟 [, 秒 [,毫秒] ] ] ] ] ] ] )

所有的参数是可选的;任何争论提供的被接受但被接受完全无视.一个字符串是创建并返回,好像由表达式 (new Date()).toString().

All of the arguments are optional; any arguments supplied are accepted but are completely ignored. A string is created and returned as if by the expression (new Date()).toString().

这篇关于通过调用prototype.constructor.apply 实例化一个JavaScript 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆