javascript: pass arguments to object constructor

感情迁移 提交于 2020-01-23 01:07:04

问题


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?


回答1:


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.




回答2:


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



回答3:


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

    // ...
}



回答4:


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/




回答5:


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(",") + ")");   


来源:https://stackoverflow.com/questions/11408722/javascript-pass-arguments-to-object-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!