2013-04-24 10 views
9

Ein sehr verwirrendes Problem, das ich mit JavaScript habe. Blick auf den Code unten ..Puzzling Javascript Konstruktor Problem

az={ 
    classes:{ 
     test:function(){ 
     this.hello=function(name){ 
      alert('hello '+name); 
     } 
     } 
    }, 
    getClass:function(name){ 
    return az.classes[name]; 
    } 
}; 
var a=new az.classes['test'](); 
a.hello('foo'); 
var b= new az.getClass('test')(); 
b.hello();// fails !!! 

im Code, wenn Sie bemerken wir eine Klasse innerhalb eines Objekts definiert az.classes. Wenn Sie versuchen, eine Instanz dieser Klasse durch neue az.classes['test]() zu erstellen, funktioniert es und a.hello() führt gut aus. aber wenn ich die Methode az.getClass('test') aufrufen, die wiederum den gleichen Konstruktor zurückgibt, aber es schlägt fehl, wenn ich sage var b=new az.getClass('test'); hier sagen b ist undefined !! und b.hello() schlägt fehl !! Ich verstehe dieses Verhalten nicht! Was ist der Unterschied zwischen neuen az.classes['test']() und neuen az.getClass('test'). Sind sie nicht das Gleiche?

+1

versuchen Sie 'var b = new (az.getClass ('test'))();' stattdessen. dann wird b wie ein – user2264587

+0

@ gurvinder372 Sie müssen eine andere Frage zu mir lesen. Ich sehe 'getClass: function (name)' – Phil

Antwort

5

Beim Instanziieren eines Konstruktors geben die ersten Parens an, was im Konstruktor verwendet werden soll.

Also wird new az.classes['test'](); den Ausdruck az.classes['test'] ausführen und die resultierende Funktion als Konstruktor verwenden.

Oder Refactoring, tut es dies:

// new az.classes['test']() 
//      ^expression left of here used as constructor! 
var MyConstructor = az.classes['test']; 
new MyConstructor(); 

jedoch führt new az.getClass('test')(); den Ausdruck az.getClass, die Ihre Klasse Getter-Funktion gibt, und versucht, die als Konstruktor zu verwenden. Dann hat Ihre Instanz versucht, mit der () ausgeführt werden.

Oder Refactoring, tut es dies:

// new az.getClass('test')(); 
//    ^expression left of here used as constructor! 
var MyConstructor = az.getClass; 
var instance = new MyConstructor('test'); 
instance(); // obviously not gonna work. 

Sehen Sie den Unterschied?

Sie können dieses Problem lösen, indem mehr Pars um den Ausdruck Verpackung, die den Konstruktor zurückgeben sollte:

new (az.getClass('test'))(); 
//      ^expression left of here used as constructor! 

oder durch Speichern der Konstruktor Verweis auf eine lokale Variable, und die Verwendung dieser dann in der nächsten Zeile. Dies ist wahrscheinlich vernünftiger und besser lesbar:

+0

Kühl !! das erklärt es !! .. danke ein Mil – user1179563

0

var b = new az.getClass('test')();

äquivalent ist, zuerst die Klasse erhalten:

var b = new az.classes.getClass('test'); 

b ist nun die Klasseaz.test, keine Instanz davon .

und dann:

b = b(); 

Konstruktor der Klasse mit dem globalen Objekt wie diese

3

Eine Konstruktor Funktion in JavaScript aufrufen kann einen Wert zurückgeben, der den Wert ersetzt, die normalerweise zurückgeschickt werden würden durch die " neuer "Ausdruck.

So new az.getClass("test")() wird zuerst az.getClass("test") auswerten, die eine Funktion zurückgeben wird. Sie rufen dann diese Funktion mit() auf, die undefiniert zurückgibt, da sie keinen Rückgabewert hat.

+0

+1 für die tatsächliche Beantwortung der Frage – Phil

+0

+1, die andere Antwort war in der Tat etwas falsch - Operator Vorrang diktiert, dass 'neue' nach '()' aufgerufen wird. –