2012-05-12 15 views
6

Grundsätzlich habe ich einen Konstruktor wie folgt aus:Geben alle Argumente an einen Konstruktor

function A() { 
    this.content = toArray(arguments); // toArray converts it to an array 
} 

Ich möchte es von einer anderen Funktion aufzurufen:

function B() { 
    return new A(); 
} 

Das Problem ist, würde ich mag auch alle an B übergebenen Argumente an A übergeben.

ich nicht apply (in einem gemeinsamen Weg) verwenden kann:

  • Es wird kein Konstruktor, wenn ich apply es nur ein altes Objekt
  • Ich kann nicht apply es die prototype, es sei denn, es gibt eine einfache Möglichkeit, es zu klonen, die ich nicht über
  • kann Ich kann nicht einfach erstellen new A, um es erneut zu übergeben; in Wirklichkeit wirft A(), wenn es keine Argumente übergeben wird, und ich möchte diese Funktionalität behalten.

Ich habe mit ein paar Lösungen kommen:

  • Ein weiterer Konstruktor!

    function C() {} 
    C.prototype = A.prototype; 
    
    function B() { 
        var obj = new C(); 
        A.apply(obj, arguments); 
        return obj; 
    } 
    
  • Eine weitere Funktion!

    function _A(_arguments) { 
        if(_arguments.length === 0) { 
         return this; 
        } 
    
        // Do initialization here! 
    } 
    
    _A.prototype.constructor = A; 
    
    function A() { 
        if(arguments.length === 0) { 
         throw new Error("That's not good."); 
        } 
    
        return new _A(toArray(arguments)); 
    } 
    
    function B() { 
        return new _A(toArray(arguments)); 
    } 
    
  • Der Rest von ihnen so ziemlich die gleiche Sache in einem anderen Format sind

Aber gibt es eine wirklich einfache und offensichtliche Art und Weise, dies zu tun?

Antwort

7

In ES5-Implementierungen können Sie Object.create verwenden, um das Objekt zu erstellen, das von A.prototype, dann .apply() das resultierende Objekt an den Konstruktor erbt.

function A() { 
    this.content = toArray(arguments); // toArray converts it to an array 
} 

function B() { 
    var obj = Object.create(A.prototype); 
    A.apply(obj, arguments); 
    return obj; 
} 

Dann könnten Sie Object.create für nicht tragende Implementierungen Shim.

if (!Object.create) 
    Object.create = function(proto) { 
     function f() {} 
     f.prototype = proto; 
     return new f; 
    } 

Natürlich ist es keine vollständige Shim, aber es ist genug für das, was Sie brauchen.


Oder Sie könnten eine Funktion erstellen, die effektiv alles für Sie erledigt.

function apply_constructor(constr, args) { 
    var obj = Object.create(constr.prototype); 
    constr.apply(obj, args); 
    return obj; 
} 

Und es wie folgt verwenden:

function B() { 
    return apply_constructor(A, arguments); 
} 
+0

'Object.create' ist perfekt. Vielen Dank! – Ryan

+0

@minitech: Gern geschehen. –

2

In ES5, können Sie binden verwenden.

function B() { 
    var args = Array.prototype.slice.call(arguments); 
    var curriedCtor = Function.prototype.bind 
     .apply(A, [null].concat(args)); 
    return new curriedCtor(); 
} 

so mit

function A(x, y) { 
    this.x = x; 
    this.y = y; 
} 

var test = B(1, 2); 

alert(JSON.stringify(test)); // alerts {"x":1,"y":2} 
Verwandte Themen