Ember.js, как работает reopenClass?
Я действительно не получаю функцию ember.js 'reopenClass. Я думал, что добавлен дополнительный код в прототип Object, поэтому все экземпляры этого объекта получат функциональность, которая была добавлена нестационарным способом. Однако это не делает. Похоже, что он только добавляет код, который можно статически выполнять. Например. У меня есть этот код:
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")
Он выводит это:
1, yo wassup
2, yoghurt
3, yoghurt
4, yofresh
Я ожидал этого:
1, yo wassup
2, yoghurt
3, yofresh
4, undefined (I think)
Итак, мой вопрос: что делает reopenClass и когда я его использую?
Ответы
Ответ 1
В общем случае reopen
добавляет методы и свойства к экземплярам, тогда как reopenClass
добавляет методы и свойства к классам.
Соответствующие тесты ember-runtime/tests/system/object/reopen_test.js и packages/ember-runtime/tests/system/object/reopenClass_test.js.
Я обновил ваш код и добавил некоторые комментарии, см. 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('----');
Ответ 2
reopen
изменяет прототип и, следовательно, изменяет экземпляры класса
reopenClass
изменяет сам конструктор и, следовательно, изменяет класс, создавая статические свойства и функции, которые доступны только для класса, но а не в каких-либо экземплярах класса.
Обратите внимание, что изменения, введенные reopen
, вступают в силу только после вызова .create()
Примеры кода на основе документа:
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