JavaScript:将参数传递给对象构造函数

4
我正在编写一个jQuery库,需要实现日期时间函数。我需要创建一个.Date()函数,它会返回一个新的Date对象。
如何将我的.Date(args)函数的参数传递给Date对象构造函数,以创建一个新的日期对象?
我尝试了类似这样的代码,其中me是插件的命名空间,me=$.jqGUI。
        //.Date(Value)
        /* Return a date object.
         * ReturnValue = Date(Value)
         */
        me.Date = function(Value){
            //pass arguments to Date constructor
            var sDate = Date.prototype.constructor.apply(null, arguments);

            console.log(sDate);

            //create a date object d
            var d = new Date(sDate);

            //validate date object
            if(d.toDateString()=="Invalid Date"){
                throw new Error("$.jqGUI.Date: Invalid Date");
            }
            else{
                return d;                   
            }
        };

在这里我将参数传递给了Date.prototype.constructor,但是无论如何都得到当前日期。 如果参数是一个日期字符串,则会被忽略。 为什么呢?


1
Date.prototype.constructorDate 完全等价。 - lanzz
5个回答

7
var args = Array.prototype.concat.apply([null], arguments);
return new (Function.prototype.bind.apply(Date, args));

如果你的目标浏览器不支持ECMAScript 5的Function.prototype.bind,该代码将无法工作。不过这种情况出现的可能性并不大,可以参考兼容性表格


不错!但是你应该添加一个注意事项,这可能不适用于任何 bind shims。 - Bergi

2
Date.prototype.constructor

这个函数相当无用,只需使用Date - 这个函数就是构造函数。

.apply(null, ...

您需要对该类型的新创建对象应用构造函数,而不是应用于 null。请参阅Use of .apply() with 'new' operator. Is this possible?
然而,应用真正的 Date 构造函数 (用于 new 的函数) 是不可能的,因为 EcmaScript 规定当 Date 作为一个函数被调用时,它必须返回当前的 UTC 时间。
你不需要这样做。相反,你只需要指定一个参数为 Date 对象,而不是接收一堆可变大小的参数。函数的用户可以按照自己的方式构建它。
您奇怪的函数似乎与 Date 构造函数完全相同。舍弃它,让用户自己应用 Date 构造函数——他知道自己想要哪种格式。
另外,您不应该使用 if(d.toDateString()=="Invalid Date"),这不是标准化的,而是依赖于具体实现。要检查有效的 Date 对象,请使用isNaN——无法解析的日期的内部表示(Date 实例的 valueof)是 NaN
建议:
me.date = function(d) {
/* gets: a Date object or something that can be transformed to a Date
returns: a valid Date object, else throws an Error */

    d = new Date(d); // works also for Date instances, uncouples them
                     // else creates new one from string or number
    if (isNaN(d))
        throw new Error("$.jqGUI.Date: Invalid Date");
    return d;
};

0

一些注意事项:

  • 永远不要使用 eval,它是危险的。
  • bind 并不总是可用的,正如指出的那样,shim 的工作方式不同。
  • Date.UTC 还接受一个变量参数列表,并返回一个可以被 Date 构造函数使用的标量。
  • apply 只需要一个类似数组的对象,而不是实际的数组,所以 arguments 就足够了。

因此,这是我首选的、浏览器安全的、完全可变的方法。请注意,它如何处理没有参数的情况,使用 Date.now()。传递一个 null 不同于没有参数,因此允许执行相同的操作。

me.Date = function(value){
    if (arguments.length < 1) value = Date.now();
    else if (arguments.length > 1) value = Date.UTC.apply(null, arguments);
    var d = new Date(value);

    // ...
}

-1

接受的答案并不理想。我只能希望任何阅读这个线程的人都会进一步调查。使用 'eval' 会产生许多副作用,我认为你不会希望在一个实用库中出现这些副作用。

以下是一个大致的解决方案:

function dateShimmer() {  
    if(arguments.length === 1){
        return new Date(arguments[0]);
    }
    else if(arguments.length > 1){
        return dateArgumentShimmer.apply(null, arguments);
    }
    return new Date();
}

function dateArgumentShimmer(a1, a2, a3, a4, a5, a6, a7){
    //Direct invocation is faster than apply/call
    switch(arguments.length){
    case 2:  return new Date(a1, a2);
    case 3:  return new Date(a1, a2, a3);
    case 4:  return new Date(a1, a2, a3, a4);
    case 5:  return new Date(a1, a2, a3, a4, a5);
    case 6:  return new Date(a1, a2, a3, a4, a5, a6);
    case 7:  return new Date(a1, a2, a3, a4, a5, a6, a7); 
    }
 }; 

这里是Jsfiddle:http://jsfiddle.net/y7Zmr/


-2

对我来说,以下内容是有效的

var args = [];
for(var i = 0; i < arguments.length; i++)
   args.push("arguments[" + i + "]");

var d = eval("new Date(" + args.join(",") + ")");   

我认为你不应该在这里使用eval,因为它很慢。你真的需要创建自己的日期函数吗? - Bergi
是的,不仅仅日期对象可以受益于此功能。另一方面,eval 函数多慢呢?大多数人现在都有配备iCore Pentium和大量内存的现代计算机。我认为这样的计算机不会有任何问题。 - demosthenes
2
传递参数:); console.log("evil >:(" - Ryan Amos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接