2016-09-19 7 views
8

Nehmen wir an, ich habe Konstruktorfunktionen Foo, Bar und Qux. Wie kann ich ein neues Objekt mit einer Delegationskette (mit diesen Konstruktoren) erstellen, die ich dynamisch dynamisch auswähle?Dynamische Delegation Vererbung

Zum Beispiel hätte ein Objekt die Delegierungskette Foo ->Bar.
Ein anderes Objekt hätte die Kette Foo ->Qux.

function Foo() { 
    this.foo = function() { 
    console.log('foo'); 
    } 
} 

function Bar() { 
    this.bar = function() { 
    console.log('bar'); 
    } 
} 

function Qux() { 
    this.qux = function() { 
    console.log('qux'); 
    } 
} 

Ein Objekt fooBar wäre in der Lage sein foo() und bar() zu nennen. Ein anderes Objekt fooQux könnte foo() und qux() aufrufen. Etc.

+0

+ rufen zu sagen statt Vererbung. Sie sollten auch die Prototypen des Konstruktors füllen, nehme ich an. – Redu

+3

Sorry ein wenig verwirrt. Was möchtest du machen? – Neal

+0

Wann möchten Sie die Kettenverbindung herstellen? Beim Erstellen einer neuen Instanz mit dem Konstruktor? Wie würde ein 'fooBar' Objekt erstellt? – nils

Antwort

6

Sie können diese Konstruktoren als Mixins verwenden:

var fooBar = {}; 
Bar.call(fooBar); 
Foo.call(fooBar); 

var fooQux = {}; 
Qux.call(fooQux); 
Foo.call(fooQux); 

Aber man könnte sie als Dekorateure schreiben wollen, vielleicht sogar das geänderte Objekt zurückkehrt, nicht als Konstrukteure, weil Sie nicht ihre Prototypen trotzdem nutzen können. So ein bequemes Muster würde

function withFoo(obj) { 
    obj.foo = function() { 
    console.log('foo'); 
    }; 
    return obj; 
} 

function withBar(obj) { 
    obj.bar = function() { 
    console.log('bar'); 
    }; 
    return obj; 
} 

function withQux(obj) { 
    obj.qux = function() { 
    console.log('qux'); 
    }; 
    return obj; 
} 

sein, so dass man sie wie

var fooBar = withFoo(withBar({})); 
var fooQux = withFoo(withQux({})); 
+0

Das würde Sie 'fooBar.bar()' lassen, nicht sicher, ob das das ist, was das OP mit * meint "... haben Sie die Delegationskette' Foo' -> 'Bar'" *, scheint mir ziemlich unklar zu sein? – adeneo

+0

@adeneo Du hast recht, es ist nicht ganz klar, also habe ich es meistens ignoriert. Soweit ich es beurteilen kann, scheint es keine Prototyp-Delegation zu geben. Aber "Foo" (das "äußere" Mixin) kann sich auf die Methoden von "Bar"/"Qux" (die "inneren" Mixins) beziehen, die bereits auf dem Objekt existieren. – Bergi

+0

"Ein Objekt' fooBar' könnte 'foo()' und 'bar()' "nennen, klingt sehr ähnlich wie Mixins. – ssube

0

Wie kommentiert verwenden kann, nicht sicher, aber ich denke, man instanceof versuchen.

Idee ist, haben eine Wrapper-Funktion, die auf Konstruktor überprüft und erforderliche Funktion aufrufen wird. Eine Alternative könnte dieselbe Funktion in allen Klassenfunktionen haben. So haben Sie gerade eine Delegation object.functionName()

Sample Fiddle

function Foo() { 
 
    this.foo = function() { 
 
    console.log('foo'); 
 
    } 
 
} 
 

 
function Bar() { 
 
    this.bar = function() { 
 
    console.log('bar'); 
 
    } 
 
} 
 

 
function Qux() { 
 
    this.qux = function() { 
 
    console.log('qux'); 
 
    } 
 
} 
 

 
function createObj() { 
 
    var index = Math.floor(Math.random() * 10) % 3; 
 
    switch (index) { 
 
    case 0: return new Foo(); 
 
    case 1: return new Bar(); 
 
    case 2: return new Qux(); 
 
    } 
 
} 
 

 
function checkObjectAndCallFunc(obj) { 
 
    if (obj instanceof Foo) { 
 
    delete obj; 
 
    obj.foo(); 
 
    } else if (obj instanceof Bar) { 
 
    delete obj; 
 
    obj.bar(); 
 
    } else if (obj instanceof Qux) { 
 
    delete obj; 
 
    obj.qux(); 
 
    } 
 
} 
 

 
function test(obj) { 
 
    obj = createObj(); 
 
    checkObjectAndCallFunc(obj); 
 
    if (count < 10) initTimeout() 
 
} 
 
var count = 0; 
 
var obj = {}; 
 

 
function initTimeout() { 
 
    count++; 
 
    setTimeout(test.bind(null, obj), 1000); 
 
} 
 
initTimeout()