Проблема с созданием класса - Значения свойств передаются другому экземпляру
Что я сделал не так?
В консоли должно быть пусто, а вместо этого [1, 2, 3, 4] То есть в экземпляре s2 оказались члены массива из экземпляра s1... Как такое могло получиться??? Код в песочнице https://fiddle.sencha.com/#fiddle/qgo Ext.define("Subpath", { segments: [], add: function(segment) { this.segments.push(segment); return segment; } }); Ext.application({ name : 'Fiddle', launch : function() { var s1 = Ext.create("Subpath"); s1.add(1); s1.add(2); s1.add(3); s1.add(4); var s2 = Ext.create("Subpath"); console.log(s2.segments); } }); Вот тут http://docs.sencha.com/extjs/5.1/cor...s/classes.html явно видно, что можно задавать значения по умолчанию для свойств класса. |
В документации видно, что такие свойства задаются через конструктор:
Ext.define('My.sample.Person', { name: 'Unknown', constructor: function(name) { if (name) { this.name = name; } }, eat: function(foodType) { alert(this.name + " is eating: " + foodType); } }); var bob = Ext.create('My.sample.Person', 'Bob'); bob.eat("Bob"); // alert("Bob is eating: Salad"); А не через самодельный сеттер. Интуитивно непонятно, конечно. |
Строка 05 содержит условие if (name) {...},. То есть предполагается, что класс можно использовать так:
var noname = Ext.create('My.sample.Person'); В этом случае name будет содержать 'Unknown'. Отсюда я делаю вывод, что строка 02 содержит значение по умолчанию. Иначе бы они написали так: name: undefined, constructor: function(name) { if (name) { this.name = name; } else { this.name = 'Unknown'; } }, В этом случае видно, что значение по умолчанию задается только в конструкторе. |
Вы путаете конфигурационные свойства, которые задаются в блоке config: {} и могут наследоваться/объединяться, с обычными свойствами, которые никаким специальным образом не обрабатываются.
Класс Ext JS - это функция-конструктор; всё, что вы задаёте в блоке Ext.define(, {…}) попадает на прототип этого конструктора. Экземпляр этого класса, соответственно, это просто объект JavaScript, который через __proto__ показывает на соответствующий класс. Ну и как отсюда очевидно, если у вас в *экземпляре* класса (т.е. в объекте) нет своего свойства segments, то будет использоваться свойство segments с *прототипа*. Т.е. каждый экземпляр класса Subpath будет обращаться к одному и тому же массиву, наступая друг другу на ноги. Обычный JavaScript, ничего сложного. ;) Решение простое: в constructor присваивайте экземпляру все свойства, которые должны быть уникальными для каждого экземпляра. Ext.define('Subpath', { /** * @property {Number[]} segments Тут живут сегменты */ constructor: function() { this.segments = []; } }); Что касается примера г-на novikov, то это как раз и есть случай конфигурационного свойства. В таких случаях велосипед изобретать не надо, а лучше использовать блок config: Ext.define('My.sample.Person', { config: { name: 'Unknown' // значение по умолчанию } }); // Значение не передано, будет использовано по умолчанию var unknown = new My.sample.Person(); console.log(unknown.getName()); // Unknown // А тут мы передаём значение явно var foo = new My.sample.Person({ name: 'foo' }); console.log(foo.getName()); // foo Особо отмечу, что первый и второй случаи друг другу совершенно не противоречат; segments это *внутреннее* свойство объекта, а name это конфигурационное свойство. Использовать и те и другие в одном объекте это совершенно обычное дело, надо просто понимать разницу. |
Цитата:
На мой взгляд не совсем логично, что свойства надо создавать в конструкторе (точнее с точки зрения JS нормально, но с точки зрения обычного ООП не привычно, а ведь Ext JS пытается имитировать обычный ООП). И если забудешь создать, то будет ссылка на общее значение. Кстати, я до сих пор не сталкивался с этой проблемой, а ведь уже сколько подобных свойств я насоздавал и пока не напарывался... Придется всю толпу классов перерыть и всюду сделать инициализацию в конструкторе... неслабо однако... Кстати, а где об этом написано в документации? |
Кстати, в свете новых сведений о создании свойств не ясно как создавать приватные свойства.
Ext.define(..., { privates: {...} }); Ведь в блоке privates их объявлять нельзя получается. Только разве комментарий можно. А в конструкторе похоже можно создавать публичные свойства. Бардачок намечается чтоли? |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Практически единственный смысл блока privates - это дать вам, как пользователю, возможность узнать о том, что в вашем наследованном классе есть метод с таким же названием, как и приватный метод в родительском классе. В отличие от публичного API, приватные методы не гарантированы по прямой и обратной совместимости между версиями; т.е. мы оставляем себе право их менять как нам заблагорассудится. Мы слишком часто натыкались на ситуации, когда пользователи в своём коде называли методы так же, как и мы в своём. Результаты бывают феерически прекрасны, но очень трудоёмки к поимке. Из этой проблемы и растут ноги у блока privates. Это наш способ дать вам знать: вот этот метод - он приватный, не трогайте его. А если потрогаете и ему не понравится, то мы не виноваты. :) |
nohuhu,
я каждый раз когда ваши сообщения в разделе читаю, жалею что движок форума не разрешает одному человеку много плюсов ставить =) |
Цитата:
Спасибо! Теперь есть чем заняться. Буду все написанные классы исправлять, там много у меня подобных свойств. Цитата:
Но это не принципиально, просто заранее надо знать, что этот момент Ext не решает и надо самому не попасться. |
Цитата:
|
Часовой пояс GMT +3, время: 04:48. |