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

后端 未结 30 3171
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条回答
  •  萌比男神i
    2020-11-22 01:01

    Here's a generalized solution that can call any constructor (except native constructors that behave differently when called as functions, like String, Number, Date, etc.) with an array of arguments:

    function construct(constructor, args) {
        function F() {
            return constructor.apply(this, args);
        }
        F.prototype = constructor.prototype;
        return new F();
    }
    

    An object created by calling construct(Class, [1, 2, 3]) would be identical to an object created with new Class(1, 2, 3).

    You could also make a more specific version so you don't have to pass the constructor every time. This is also slightly more efficient, since it doesn't need to create a new instance of the inner function every time you call it.

    var createSomething = (function() {
        function F(args) {
            return Something.apply(this, args);
        }
        F.prototype = Something.prototype;
    
        return function(args) {
            return new F(args);
        }
    })();
    

    The reason for creating and calling the outer anonymous function like that is to keep function F from polluting the global namespace. It's sometimes called the module pattern.

    [UPDATE]

    For those who want to use this in TypeScript, since TS gives an error if F returns anything:

    function construct(constructor, args) {
        function F() : void {
            constructor.apply(this, args);
        }
        F.prototype = constructor.prototype;
        return new F();
    }
    

提交回复
热议问题