Use of .apply() with 'new' operator. Is this possible?

后端 未结 30 2748
Happy的楠姐
Happy的楠姐 2020-11-22 00:39

In JavaScript, I want to create an object instance (via the new operator), but pass an arbitrary number of arguments to the constructor. Is this possible?

30条回答
  •  囚心锁ツ
    2020-11-22 01:06

    Solution without ES6 or polyfills:

    var obj = _new(Demo).apply(["X", "Y", "Z"]);
    
    
    function _new(constr)
    {
        function createNamedFunction(name)
        {
            return (new Function("return function " + name + "() { };"))();
        }
    
        var func = createNamedFunction(constr.name);
        func.prototype = constr.prototype;
        var self = new func();
    
        return { apply: function(args) {
            constr.apply(self, args);
            return self;
        } };
    }
    
    function Demo()
    {
        for(var index in arguments)
        {
            this['arg' + (parseInt(index) + 1)] = arguments[index];
        }
    }
    Demo.prototype.tagged = true;
    
    
    console.log(obj);
    console.log(obj.tagged);
    


    output

    Demo {arg1: "X", arg2: "Y", arg3: "Z"}


    ... or "shorter" way:

    var func = new Function("return function " + Demo.name + "() { };")();
    func.prototype = Demo.prototype;
    var obj = new func();
    
    Demo.apply(obj, ["X", "Y", "Z"]);
    


    edit:
    I think this might be a good solution:

    this.forConstructor = function(constr)
    {
        return { apply: function(args)
        {
            let name = constr.name.replace('-', '_');
    
            let func = (new Function('args', name + '_', " return function " + name + "() { " + name + "_.apply(this, args); }"))(args, constr);
            func.constructor = constr;
            func.prototype = constr.prototype;
    
            return new func(args);
        }};
    }
    

提交回复
热议问题