2012-04-22 1 views
24

Ich bekomme nicht wirklich die Funktion von reopenClass von ember.js. Ich dachte, es fügte dem Prototyp des Objekts zusätzlichen Code hinzu, so dass alle Instanzen dieses Objekts die Funktionalität erhielten, die auf nicht-statische Weise hinzugefügt wurde. Es tut dies jedoch nicht. Es sieht so aus, als würde nur Code hinzugefügt, der statisch ausgeführt werden kann. Zum Beispiel. Ich habe diesen Code:Ember.js Wie funktioniert reopenClass?

Logger = Ember.Object.extend({ 
    log: function(thing) { 
    console.log(thing + ' wassup'); 
    } 
}); 

var logger = Logger.create(); 
logger.log("1, yo") 

logger.reopen({ 
    log: function(name) { 
     console.log(name + 'ghurt') 
    } 
}); 
logger.log("2, yo") 

Logger.reopenClass({ 
    log: function(name) { 
     console.log(name + 'fresh') 
    } 
}); 
logger.log("3, yo") 
Logger.log("4, yo") 

Es gibt dieses:

1, yo wassup 
2, yoghurt 
3, yoghurt 
4, yofresh 

Was ich erwartet war:

1, yo wassup 
2, yoghurt 
3, yofresh 
4, undefined (I think) 

Also meine Frage ist: Was ist reopenClass tun und wenn ich verwenden es?

Antwort

44

Im Allgemeinen reopen fügen Methoden und Eigenschaften zu Instanzen während reopenClass Methoden und Eigenschaften zu Klassen erstellt. Die entsprechenden Tests sind ember-runtime/tests/system/object/reopen_test.js und packages/ember-runtime/tests/system/object/reopenClass_test.js.

Ich habe den Code aktualisiert und einige Kommentare hinzugefügt, siehe http://jsfiddle.net/pangratz666/yWKBF/:

Logger = Ember.Object.extend({ 
    log: function(thing) { 
     console.log(thing + ' wassup'); 
    } 
}); 

var logger1 = Logger.create(); 
var logger2 = Logger.create(); 

// instances of Logger have a 'wassup' method 
try { Logger.log("1, yo"); } catch (e) {} // Object (subclass of Ember.Object) has no method 'log' 
logger1.log("1, yo"); // 1, yo wassup 
logger2.log("1, yo"); // 1, yo wassup 

console.log('----'); 

// overwrite log of concrete logger instance logger1 
logger1.reopen({ 
    log: function(name) { 
     console.log(name + ' ghurt'); 
    } 
}); 

try { Logger.log("1, yo"); } catch (e) {} // Object (subclass of Ember.Object) has no method 'log' 
logger1.log("2, yo"); // 2, yo ghurt 
logger2.log("2, yo"); // 2, yo wassup 

console.log('----'); 

// classes of Logger have a 'fresh' method 
Logger.reopenClass({ 
    log: function(name) { 
     console.log(name + ' fresh'); 
    } 
}); 

Logger.log("3, yo"); // 3, yo fresh 
logger1.log("3, yo"); // 3, yo ghurt 
logger2.log("3, yo"); // 3, yo wassup 

console.log('----'); 

// new* instances of Logger have from now on a 'dawg' method 
// * this will likely change in the future so already existing instances will reopened too 
Logger.reopen({ 
    log: function(name) { 
     console.log(name + ' dawg'); 
    } 
}); 

Logger.log("4, yo"); // 4, yo fresh 
logger1.log("4, yo"); // 4, yo ghurt 
logger2.log("4, yo"); // 4, yo wassup 
Logger.create().log("4, yo"); // 4, yo dawg 

console.log('----'); 

+9

Ok, so Wenn ich das r iight logger.reopen() fügt den Code nur zur Logger-Instanz hinzu, Logger.reopen() fügt Code für jede neue Instanz hinzu, die erstellt wird (vorhandene Instanzen werden nicht geändert) und Logger.reopenClass() fügt Code hinzu, der statisch ist die Logger-Klasse (sie kann nicht von Instanzen, nur statisch aufgerufen werden). Richtig? – koenpeters

+0

Ja, das ist richtig. – pangratz

+2

Ok. Danke für das Licht. Es fiel mir schwer, dies zu verstehen (wie in: Ich habe es nicht verstanden) aus der Dokumentation unter http://emberjs.com/documentation/. – koenpeters

0

reopen Änderungen Prototyp und ändert somit Instanzen einer Klasse

reopenClass ändert den Konstruktor selbst und somit ändert die Klasse durch Erstellen statische Eigenschaften und Funktionen das sind nur für die Klasse, aber nicht für alle Instanzen der Klasse.

Hinweis, dass die von reopen eingeführten Änderungen werden erst nach .create()

Codebeispiele basieren auf dem doc Aufruf:

http://emberjs.com/api/classes/Ember.Application.html#method_reopen

MyObject = Ember.Object.extend({ 
    name: 'an object' 
}); 

o = MyObject.create(); 
o.get('name'); // 'an object' 

MyObject.reopen({ 
    say: function(msg){ 
    console.log(msg); 
    } 
}) 

try{ 
    o.say("hey"); 
} catch(e) { 
    console.log(e); // o.say is not a function (...yet) 
} 
o2 = MyObject.create(); 
o2.say("hello"); // logs "hello" 

o.say("goodbye"); // logs "goodbye" 

http://emberjs.com/api/classes/Ember.Application.html#method_reopenClass

MyObject = Ember.Object.extend({ 
    name: 'an object' 
}); 

MyObject.reopenClass({ 
    canBuild: false 
}); 

MyObject.canBuild; // false 
o = MyObject.create(); 
o.canBuild; // undefined