Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/424.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将.apply()与“new”运算符一起使用。这可能吗?_Javascript_Oop_Class_Inheritance_Constructor - Fatal编程技术网

Javascript 将.apply()与“new”运算符一起使用。这可能吗?

Javascript 将.apply()与“new”运算符一起使用。这可能吗?,javascript,oop,class,inheritance,constructor,Javascript,Oop,Class,Inheritance,Constructor,在JavaScript中,我希望通过new操作符创建一个对象实例,但将任意数量的参数传递给构造函数。这可能吗 我想做的是这样的事情,但下面的代码不起作用: function Something(){ // init stuff } function createSomething(){ return new Something.apply(null, arguments); } var s = createSomething(a,b,c); // 's' is an instan

在JavaScript中,我希望通过new操作符创建一个对象实例,但将任意数量的参数传递给构造函数。这可能吗

我想做的是这样的事情,但下面的代码不起作用:

function Something(){
    // init stuff
}
function createSomething(){
    return new Something.apply(null, arguments);
}
var s = createSomething(a,b,c); // 's' is an instance of Something
答案

从这里的回复来看,显然没有内置的呼叫方式。请向新的接线员申请。然而,人们对这个问题提出了一些非常有趣的解决方案

我的首选解决方案是修改它以传递arguments属性:

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

    return function() {
        return new F(arguments);
    }
})();

如果您对基于评估的解决方案感兴趣

function createSomething() {
    var q = [];
    for(var i = 0; i < arguments.length; i++)
        q.push("arguments[" + i + "]");
    return eval("new Something(" + q.join(",") + ")");
}

您可以将init内容移动到某个原型的单独方法中:

function Something() {
    // Do nothing
}

Something.prototype.init = function() {
    // Do init stuff
};

function createSomething() {
    var s = new Something();
    s.init.apply(s, arguments);
    return s;
}

var s = createSomething(a,b,c); // 's' is an instance of Something

这是一个通用的解决方案,它可以调用除本机构造函数之外的任何构造函数,本机构造函数在作为函数调用时表现不同,如字符串、数字、日期等,并带有参数数组:

function construct(constructor, args) {
    function F() {
        return constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    return new F();
}
通过调用constructClass[1,2,3]创建的对象将与使用新的Class1,2,3创建的对象相同

您还可以创建更具体的版本,这样就不必每次都通过构造函数。这也稍微有效一些,因为它不需要每次调用时都创建内部函数的新实例

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

    return function(args) {
        return new F(args);
    }
})();
这样创建和调用外部匿名函数的原因是为了防止函数F污染全局命名空间。它有时被称为模块模式

[更新]

对于那些希望在TypeScript中使用此选项的用户,因为如果F返回任何内容,TS将给出一个错误:

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

不能像使用新运算符一样使用可变参数数调用构造函数

您可以做的是稍微更改构造函数。而不是:

function Something() {
    // deal with the "arguments" array
}
var obj = new Something.apply(null, [0, 0]);  // doesn't work!
改为这样做:

function Something(args) {
    // shorter, but will substitute a default if args.x is 0, false, "" etc.
    this.x = args.x || SOME_DEFAULT_VALUE;

    // longer, but will only put in a default if args.x is not supplied
    this.x = (args.x !== undefined) ? args.x : SOME_DEFAULT_VALUE;
}
var obj = new Something({x: 0, y: 0});
或者,如果必须使用阵列:

function Something(args) {
    var x = args[0];
    var y = args[1];
}
var obj = new Something([0, 0]);

@Matthew答案的改进版本。这种形式通过将temp类存储在闭包中获得了轻微的性能优势,并且可以灵活地使用一个函数来创建任何类

var applyCtor = function(){
    var tempCtor = function() {};
    return function(ctor, args){
        tempCtor.prototype = ctor.prototype;
        var instance = new tempCtor();
        ctor.prototype.constructor.apply(instance,args);
        return instance;
    }
}();

这将通过调用applyCtorclass[arg1,arg2,argn]来使用

假设您有一个Items构造函数,它会将您抛出的所有参数都存储起来:

function Items () {
    this.elems = [].slice.call(arguments);
}

Items.prototype.sum = function () {
    return this.elems.reduce(function (sum, x) { return sum + x }, 0);
};
您可以使用Object.create创建实例,然后使用该实例应用:

var items = Object.create(Items.prototype);
Items.apply(items, [ 1, 2, 3, 4 ]);

console.log(items.sum());
运行时打印10,因为1+2+3+4==10:

$ node t.js
10

另请参见CoffeeScript是如何做到这一点的

s=新事物[a,b,c]

变成:

var s;
s = (function(func, args, ctor) {
  ctor.prototype = func.prototype;
  var child = new ctor, result = func.apply(child, args);
  return Object(result) === result ? result : child;
})(Something, [a, b, c], function(){});

通过使用arguments.callee(也称为creator/factory函数本身)来解决重用临时F构造函数的问题也很有趣:

多亏了这里的帖子,我才这样使用它:

SomeClass = function(arg1, arg2) {
    // ...
}

ReflectUtil.newInstance('SomeClass', 5, 7);
和执行:

/**
 * @param strClass:
 *          class name
 * @param optionals:
 *          constructor arguments
 */
ReflectUtil.newInstance = function(strClass) {
    var args = Array.prototype.slice.call(arguments, 1);
    var clsClass = eval(strClass);
    function F() {
        return clsClass.apply(this, args);
    }
    F.prototype = clsClass.prototype;
    return new F();
};
在咖啡脚本中:

construct = (constructor, args) ->
    F = -> constructor.apply this, args
    F.prototype = constructor.prototype
    new F


这个答案有点晚了,但我想任何看到它的人都可以使用它。有一种方法可以使用apply返回新对象。尽管它需要对对象声明进行一点更改

function testNew() {
    if (!( this instanceof arguments.callee ))
        return arguments.callee.apply( new arguments.callee(), arguments );
    this.arg = Array.prototype.slice.call( arguments );
    return this;
}

testNew.prototype.addThem = function() {
    var newVal = 0,
        i = 0;
    for ( ; i < this.arg.length; i++ ) {
        newVal += this.arg[i];
    }
    return newVal;
}

testNew( 4, 8 ) === { arg : [ 4, 8 ] };
testNew( 1, 2, 3, 4, 5 ).addThem() === 15;
更新:我已将第一个示例更改为任意数量的参数求和,而不是仅求两个。

使用ECMAScript 5,情况变得非常清楚:

function newCall(Cls) {
    return new (Function.prototype.bind.apply(Cls, arguments));
    // or even
    // return new (Cls.bind.apply(Cls, arguments));
    // if you know that Cls.bind has not been overwritten
}
它可以按如下方式使用:

var s = newCall(Something, a, b, c);
甚至直接:

var s = new (Function.prototype.bind.call(Something, null, a, b, c));

var s = new (Function.prototype.bind.apply(Something, [null, a, b, c]));
即使有Date:

编辑

一点解释: 我们需要在接受有限数量参数的函数上运行new。bind方法允许我们这样做:

var f = Cls.bind(anything, arg1, arg2, ...);
result = new f();
anywhere参数无关紧要,因为new关键字会重置f的上下文。然而,出于句法上的原因,它是必需的。现在,对于bind调用:我们需要传递一个可变数量的参数,所以这就完成了:

var f = Cls.bind.apply(Cls, [anything, arg1, arg2, ...]);
result = new f();
让我们把它包装在一个函数中。Cls作为参数0传递,所以它将是我们的任何东西

实际上,根本不需要临时f变量:

function newCall(Cls /*, arg1, arg2, ... */) {
    return new (Cls.bind.apply(Cls, arguments))();
}

最后,我们应该确保bind是我们真正需要的。Cls.bind可能已被覆盖。因此,用Function.prototype.bind替换它,我们得到的最终结果如上所述。

任何函数,即使是构造函数,都可以接受可变数量的参数。每个函数都有一个arguments变量,可以将该变量转换为具有[].slice.callarguments的数组

上述测试产生以下输出:

s.options === "1,2,3,4": true
z.options === "9,10,11": true
@马修 我认为最好也修复构造函数属性

// Invoke new operator with arbitrary arguments
// Holy Grail pattern
function invoke(constructor, args) {
    var f;
    function F() {
        // constructor returns **this**
        return constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    f = new F();
    f.constructor = constructor;
    return f;
}
如果目标浏览器不支持ECMAScript 5 Function.prototype.bind,则代码将无法工作。但可能性不大,请参见。

以下是我的createSomething版本:

基于此,我尝试模拟JavaScript的新关键字:

//JavaScript 'new' keyword simulation
function new2() {
    var obj = {}, args = Array.prototype.slice.call(arguments), fn = args.shift();
    obj = fn.apply(obj, args) || obj;
    Object.setPrototypeOf(obj, fn.prototype); //or: obj.__proto__ = fn.prototype;
    return obj;
}
我对它进行了测试,似乎它在所有情况下都能正常工作。它也适用于本机构造函数,如Date。以下是一些测试:

//test
new2(Something);
new2(Something, 1, 2);

new2(Date);         //"Tue May 13 2014 01:01:09 GMT-0700" == new Date()
new2(Array);        //[]                                  == new Array()
new2(Array, 3);     //[undefined × 3]                     == new Array(3)
new2(Object);       //Object {}                           == new Object()
new2(Object, 2);    //Number {}                           == new Object(2)
new2(Object, "s");  //String {0: "s", length: 1}          == new Object("s")
new2(Object, true); //Boolean {}                          == new Object(true)

我刚遇到这个问题,我就这样解决了:

function instantiate(ctor) {
    switch (arguments.length) {
        case 1: return new ctor();
        case 2: return new ctor(arguments[1]);
        case 3: return new ctor(arguments[1], arguments[2]);
        case 4: return new ctor(arguments[1], arguments[2], arguments[3]);
        //...
        default: throw new Error('instantiate: too many parameters');
    }
}

function Thing(a, b, c) {
    console.log(a);
    console.log(b);
    console.log(c);
}

var thing = instantiate(Thing, 'abc', 123, {x:5});

是的,这有点难看,但它解决了问题,而且非常简单。

这种构造函数方法在使用和不使用新关键字的情况下都有效:

它假定支持Ob 但是,如果您支持较旧的浏览器,您可以随时填充它


这里有一个。

修改的@Matthew答案。在这里,我可以传递任意数量的参数来正常工作,而不是数组。此外,“某物”未硬编码到:

function createObject( constr ) {   
  var args =  arguments;
  var wrapper =  function() {  
    return constr.apply( this, Array.prototype.slice.call(args, 1) );
  }

  wrapper.prototype =  constr.prototype;
  return  new wrapper();
}


function Something() {
    // init stuff
};

var obj1 =     createObject( Something, 1, 2, 3 );
var same =     new Something( 1, 2, 3 );

这一班轮应该做到:

new (Function.prototype.bind.apply(Something, [null].concat(arguments)));

如果您的环境支持,您可以这样简单地使用它

function Something() {
    // init stuff
}

function createSomething() {
    return new Something(...arguments);
}
注意:现在ECMA脚本2015的规范已经发布,大多数JavaScript引擎都在积极地实现它,这将是实现这一点的首选方法


您可以检查Spread操作符在一些主要环境中的支持情况。

是的,我们可以,javascript本质上更像是原型继承

function Actor(name, age){
  this.name = name;
  this.age = age;
}

Actor.prototype.name = "unknown";
Actor.prototype.age = "unknown";

Actor.prototype.getName = function() {
    return this.name;
};

Actor.prototype.getAge = function() {
    return this.age;
};
当我们用new创建一个对象时,我们创建的对象将继承getAge,但是如果我们使用apply。。。或者打电话。。。要调用Actor,我们将为此传递一个对象,但传递的对象不会从Actor.prototype继承

除非,我们直接传递apply或调用Actor.prototype,但是。。。。这将指向Actor.prototype,this.name将写入:Actor.prototype.name。因此会影响使用Actor创建的所有其他对象…因为我们覆盖了原型而不是实例

var rajini = new Actor('Rajinikanth', 31);
console.log(rajini);
console.log(rajini.getName());
console.log(rajini.getAge());

var kamal = new Actor('kamal', 18);
console.log(kamal);
console.log(kamal.getName());
console.log(kamal.getAge());
让我们试试应用程序

通过将Actor.prototype作为第一个参数传递给Actor.call,当Actor函数运行时,它将执行这个.name=name,因为它将指向Actor.prototype,这个.name=name;表示Actor.prototype.name=name

回到最初的问题,如何使用新操作符和apply,这是我的看法

Function.prototype.new = function(){
    var constructor = this;
    function fn() {return constructor.apply(this, args)}
    var args = Array.prototype.slice.call(arguments);
    fn.prototype = this.prototype;
    return new fn
};

var thalaivar = Actor.new.apply(Parent, ["Thalaivar", 30]);
console.log(thalaivar);
在ES6中,非常方便:

Reflect.construct(F, args)

虽然其他方法可行,但它们过于复杂。在Clojure中,通常创建一个实例化类型/记录的函数,并将该函数用作实例化机制。将其转换为JavaScript:

function Person(surname, name){
  this.surname = surname;
  this.name = name;
}

function person(surname, name){ 
  return new Person(surname, name);
}
通过采用这种方法,您可以避免使用除上述之外的新方法。当然,这个函数在使用apply或其他函数编程特性时没有问题

var doe  = _.partial(person, "Doe");
var john = doe("John");
var jane = doe("Jane");
通过使用这种方法,您的所有类型构造函数(例如Person)都是普通的、不做任何事情的构造函数。您只需传入参数并将它们分配给同名的属性。在构造函数函数中会出现毛茸茸的细节,例如person

创建这些额外的构造函数并不麻烦,因为它们无论如何都是一种很好的实践。它们可能很方便,因为它们允许您潜在地拥有多个具有不同细微差别的构造函数。

这很有效

var cls = Array; //eval('Array'); dynamically
var data = [2];
new cls(...data);

由于ES6,这可以通过扩展运算符实现,请参阅

这个答案已经在评论中给出了,但似乎被大多数没有ES6或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);
输出 演示{arg1:X,arg2:Y,arg3:Z} ... 或更短的方式:

var func = new Function("return function " + Demo.name + "() { };")();
func.prototype = Demo.prototype;
var obj = new func();

Demo.apply(obj, ["X", "Y", "Z"]);
编辑: 我认为这可能是一个很好的解决方案:

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

其实最简单的方法是:

function Something (a, b) {
  this.a = a;
  this.b = b;
}
function createSomething(){
    return Something;
}
s = new (createSomething())(1, 2); 
// s == Something {a: 1, b: 2}

来自@jordancpaul答案的修订解决方案

var applyCtor = function(ctor, args)
{
    var instance = new ctor();
    ctor.prototype.constructor.apply(instance, args);
    return instance;
}; 

创建一个匿名原型,并使用参数对其应用某物原型,然后创建该匿名原型的新实例。这样做的一个缺点是它不会通过s instanceof Something检查,尽管它是相同的,但它基本上是一个克隆实例

function Something(){
    // init stuff
}
function createSomething(){
    return new (function(){Something.apply(this, arguments)});
}
var s = createSomething(a,b,c); // 's' is an instance of Something

使用eval比直接使用apply更慢,更容易出错。是的,好主意。我可以创建一个init方法,然后在上面使用apply。正如我对Ionut方法的评论一样,如果不修改构造函数的体系结构,就没有办法做到这一点,这有点遗憾。但这看起来是一个务实的解决方案。好吧,很公平。这基本上将参数的数量限制为对象或数组中的一个,但允许在其中包含任意数量的属性。是。好吧,它根本不限制参数的数量,实际上,您只需使用其中一个参数作为可选参数的容器,只是对象或数组通常是最有用的容器。您经常会在构造函数中看到这种模式;它允许命名参数用于自文档化源代码以及可选参数。谢谢Matthew。有趣的是,在飞行中结束。虽然您的示例显示调用函数只允许一个参数和一个参数数组,但我想这可以修改为将其传递给参数var。我将接受这一个作为我的首选解决方案,因为它不需要修改原始构造函数,我没有在我的原始问题中指定它作为一个要求,但我还是很感激它。因此,构造函数可以以任何方式编写,而调用函数可以独立编写以增加更多的便利性。这不适用于日期、字符串或任何其他在作为构造函数调用时表现不同的函数。嗨,Matthew,最好也修复构造函数属性。你答案的增强版。一个缺点是生成的构造对象myObj.con

structor.name属性将被设置为F。当查看调试器内部的堆栈跟踪和向下钻取转储时,这有点糟糕,因为调试器在任何地方都使用该名称。如果有Object.create可用,这是另一种很好的方法。所有其他答案在当时都很好,但现在这种方法显然是赢家。在将来,Reflect.construct可能会更好,尽管CoffeeScript中的[Matthew Crumley的解决方案][1]:construct=constructor,args->F=->constructor.apply,args F.prototype=constructor.prototype new F createSomething=->F=args->Something.apply this.args F.prototype=Something.prototype return->new Something参数[1]:我认为这个线程的好处是new做了两件事:我设置了原型,ii将该构造函数和该集合应用于所述对象/原型组合。您可以通过Object.create实现这一点,也可以通过使用闭包对Object.create进行转换并捕获上下文来实现。我通过将类作为参数传入外部函数来对其进行了推广。因此,这基本上是一个工厂-工厂的问题。@Pumbaa80给出的答案似乎是更好的解决方案,ES6 Traceur也将其用于polyfill spread operator而且它在Chrome上也快了一点:有人能解释一下为什么这个家伙不能像var s=new something a,b,c那样做吗?我搞不懂:/你说Function.bind可以代替Function.prototype.bind是对的,为了清楚起见,我把它留下了。毕竟,任何函数都可以使用:eval.bind将保存更多的代码,但这实在太令人困惑了。@Pumbaa80我的坏,还原了我的编辑。我测试了新的Function.prototype.bind.applyArray[1,2,3];,但是忘记了你的newCall函数已经收到了一个cls参数。有趣但重要的是要记住IE8只支持我发现你的解决方案非常好。但这令人困惑。因为在第一个样本中,你写了一些东西,a,b,c;其中a将是绑定的上下文,但在您的第二个示例中,您提到的did上下文是没有意义的-因此您发送null。对我来说,这是非常困惑的,你相信我,我想了三天吗无论如何,要持久化到第二个示例的第一个代码需要是:function newCallCls{var arr=Array.prototype.slice.callarguments;arr.shift;return new function.prototype.bind.applyCls[null,arr];small fix:而不是[null,arr]-[null].concatarrof当然,arguments.callee已折旧,但您仍然可以直接通过name@busticated:完全正确,我在第二个代码段中没有使用它。这个解决方案唯一的问题是,它会在同一个对象上用不同的参数运行构造函数两次。@WillTomlins:它将在不同的上下文中运行构造函数两次。虽然我不确定参数将如何更改。是否要澄清?我的意思是,将创建对象,然后在该对象上运行构造函数而不带任何参数,然后在这种情况下,将在相同的对象上再次运行构造函数a、 b&c。当你的构造函数需要某些参数时,你可能会发现有些尴尬。我认为你是对的,修复构造函数是有用的,除非应用程序从未检查它,这在编写库时是无法暗示的。我已经在一个调试器中查看过它,该调试器评估newObject.constructor==ConstructorFunction断点。事实证明根本不需要赋值,它在@MatthewCrumley的代码中设置正确。这并不能解决OP的问题。请注意,当创建变量s和z时,传递给某个对象的参数数是静态的。警告:proto属性已弃用,不应使用。相反,应使用Object.getPrototypeOfproto getter的ead,以确定对象的[[Prototype]]。对[[Prototype]]进行变异对于一个对象,无论它是如何实现的,都是非常不鼓励的,因为它非常慢,并且不可避免地会减慢现代JavaScript实现中后续的执行。关于proto对象,你是对的。这就是为什么我使用object.setPrototypeOf。而整件事只是对“new”关键字的模拟。它清楚地显示了w JavaScript的新关键字的工作原理以及它实际如何实例化对象。接受的答案不起作用,但这个答案起作用。与@user123444555621的建议有什么不同?你能在答案中对不同之处添加一些解释吗?这是一个非常好的解决方案。也适用于@user12344555621的解决方案失败的地方。@wilt:jsiddle必须具有[null].concatargs,而不仅仅是bind.apply中的参数。检查@trss数组中的附加null在做什么?这是在中提到的thisArg。这并不完全相同,因为Person函数中的arguments.length始终为2,而使用新函数.prototype.bind.applyPerson,perso中的参数
n也会将参数设置为Person内部的正确值。我一直在尝试理解如何使用Reflect.construct将其应用于我正在构造F的新类,但似乎F内部的上下文仍然是新的,并且它的旧属性不会延续,有人看到过关于如何使用Reflect.construct的好博客帖子或例子吗?这里是最好的答案!我们鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接的最相关部分,以防目标站点无法访问或永久脱机。使用扩展语法,我们可以向构造函数传递可变数量的参数。作为参数传递一个类似数组的iterable类型,最后数组将扩展到构造函数中的每个参数。
Reflect.construct(F, args)
function Person(surname, name){
  this.surname = surname;
  this.name = name;
}

function person(surname, name){ 
  return new Person(surname, name);
}
var doe  = _.partial(person, "Doe");
var john = doe("John");
var jane = doe("Jane");
var cls = Array; //eval('Array'); dynamically
var data = [2];
new cls(...data);
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);
var func = new Function("return function " + Demo.name + "() { };")();
func.prototype = Demo.prototype;
var obj = new func();

Demo.apply(obj, ["X", "Y", "Z"]);
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);
    }};
}
function Something (a, b) {
  this.a = a;
  this.b = b;
}
function createSomething(){
    return Something;
}
s = new (createSomething())(1, 2); 
// s == Something {a: 1, b: 2}
var applyCtor = function(ctor, args)
{
    var instance = new ctor();
    ctor.prototype.constructor.apply(instance, args);
    return instance;
}; 
function Something(){
    // init stuff
}
function createSomething(){
    return new (function(){Something.apply(this, arguments)});
}
var s = createSomething(a,b,c); // 's' is an instance of Something