简体   繁体   中英

javascript: pass arguments to object constructor

i am writing a jquery lib and i need to implement Datetime functions. i need to create a .Date() function which return a new Date object.

How to pass arguments of my .Date(args) function to Date object constructor so to create a new date object?

i tried something like this, me is the plugin namespace, 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;                   
            }
        };

here i pass to Date.prototype.constructor the arguments but i get in any case the current date. if arguments is a date string it is ignored. why?

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

If your target browser doesn't support ECMAScript 5 Function.prototype.bind, the code won't work. It is not very likely though, see compatibilty table .

Date.prototype.constructor

is quite useless, just use Date - the function is the constructor.

.apply(null, ...

You will need to apply a constructor on a newly created object of that type, not on null . See Use of .apply() with 'new' operator. Is this possible?

However, it is impossible to apply the real Date constructor (the function used for new ), because EcmaScript specifies that when Date is called as a function it must return the current UTC time.


Anyway, you should not need this. Instead of receiving a bunch of arguments (of variable size), you should just specify a parameter to be a Date object. The user of the function can build that how he wants.

Your odd-looking function seems to do exactly the same as the Date constructor. Throw it away, and let the user apply Date himself - he knows which format he wants.

Also, you should not use if(d.toDateString()=="Invalid Date") , this is not standardisized but implementation-dependent. To check for a valid Date object, just use isNaN - the internal representation (valueof the Date instance) of unparsable dates is NaN .

Suggestion:

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;
};

A few notes:

  • Never use eval , it is dangerous.
  • bind isn't always available and as pointed out, shims don't work the same.
  • Date.UTC also takes a variable argument list and returns a scalar that can be used by the Date constructor.
  • apply only requires an array like object, not an actual array, so arguments is good enough.

So here is my preferred, browser safe, totally variable method. Notice how it handles no arguments with Date.now() . Passing a null is not the same as no arguments so that is allowed to perform the same.

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

    // ...
}

The accepted answer is not ideal. I can only hope that anyone reading this thread will investigate further. Using 'eval' has a host of side-affects that I don't think you would want in a util-lib.

Here's a rough take at what you could do:

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 here: http://jsfiddle.net/y7Zmr/

ok for me the following was worked

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM