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

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

问题描述

让我先谈谈我正在尝试做的具体例子。

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

我有一个年,月,日,小时,分钟,秒的数组以及 [2008,10,8,50,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 ])

如何将我的数组传递给此构造函数以获取新的日期实例? [更新:我的问题实际上超出了这个具体的例子。我想要内置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 :(

它也不适用于数字:

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

也许这对于内部对象是不可能的?我用Firefox BTW进行测试。

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

推荐答案

我对自己做了更多的调查并得出了这是一个不可能的壮举,由于Date类的实现方式。

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 是一个Date实例内部值 NaN 因此,

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始终在epoch之前返回一个日期。

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).

注意函数
调用日期( ...)不等于
对象创建表达式 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日期([年[,月份[,日期[,小时[,分钟[,秒[,
ms]]]]] ]])

所有
参数都是可选的;提供的任何参数
都被接受但是
完全被忽略。一个字符串是
创建并返回,就像
表达式(new Date())。toString()

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

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