15.07.2015, 17:50
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Проблема с созданием класса - Значения свойств передаются другому экземпляру
Что я сделал не так?
В консоли должно быть пусто, а вместо этого [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
явно видно, что можно задавать значения по умолчанию для свойств класса.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 15.07.2015 в 18:01.
|
|
15.07.2015, 18:28
|
Профессор
|
|
Регистрация: 19.11.2012
Сообщений: 178
|
|
В документации видно, что такие свойства задаются через конструктор:
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");
А не через самодельный сеттер. Интуитивно непонятно, конечно.
Последний раз редактировалось novikov, 15.07.2015 в 18:32.
|
|
15.07.2015, 18:37
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Строка 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';
}
},
В этом случае видно, что значение по умолчанию задается только в конструкторе.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 15.07.2015 в 18:43.
|
|
15.07.2015, 21:14
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Вы путаете конфигурационные свойства, которые задаются в блоке 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 это конфигурационное свойство. Использовать и те и другие в одном объекте это совершенно обычное дело, надо просто понимать разницу.
|
|
15.07.2015, 21:26
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
Ну и как отсюда очевидно, если у вас в *экземпляре* класса (т.е. в объекте) нет своего свойства segments, то будет использоваться свойство segments с *прототипа*. Т.е. каждый экземпляр класса Subpath будет обращаться к одному и тому же массиву, наступая друг другу на ноги. Обычный JavaScript, ничего сложного.
|
Не понятно как система классов Ext JS допустила эту странную ситуацию. Зачем такое может вообще понадобиться? Чтобы иметь доступ к общему массиву (или что там будет вложено в свойство).
На мой взгляд не совсем логично, что свойства надо создавать в конструкторе (точнее с точки зрения JS нормально, но с точки зрения обычного ООП не привычно, а ведь Ext JS пытается имитировать обычный ООП). И если забудешь создать, то будет ссылка на общее значение.
Кстати, я до сих пор не сталкивался с этой проблемой, а ведь уже сколько подобных свойств я насоздавал и пока не напарывался... Придется всю толпу классов перерыть и всюду сделать инициализацию в конструкторе... неслабо однако...
Кстати, а где об этом написано в документации?
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 15.07.2015 в 21:29.
|
|
15.07.2015, 21:32
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Кстати, в свете новых сведений о создании свойств не ясно как создавать приватные свойства.
Ext.define(..., {
privates: {...}
});
Ведь в блоке privates их объявлять нельзя получается. Только разве комментарий можно. А в конструкторе похоже можно создавать публичные свойства. Бардачок намечается чтоли?
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
15.07.2015, 23:57
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
Не понятно как система классов Ext JS допустила эту странную ситуацию. Зачем такое может вообще понадобиться? Чтобы иметь доступ к общему массиву (или что там будет вложено в свойство).
|
Подождите, а как вы предполагаете обойти базовые свойства языка в библиотеке? :))
Цитата:
|
На мой взгляд не совсем логично, что свойства надо создавать в конструкторе (точнее с точки зрения JS нормально, но с точки зрения обычного ООП не привычно, а ведь Ext JS пытается имитировать обычный ООП). И если забудешь создать, то будет ссылка на общее значение.
|
Ну, вот такой вот язык этот JavaScript. Выбора какбэ нет, скорбь и пичалька.
Цитата:
|
Кстати, я до сих пор не сталкивался с этой проблемой, а ведь уже сколько подобных свойств я насоздавал и пока не напарывался... Придется всю толпу классов перерыть и всюду сделать инициализацию в конструкторе... неслабо однако…
|
Большая часть таких конструкций может работать просто по случайности, как оно обычно и бывает. Если не создаёте более одного экземпляра класса одновременно, то и проблем как будто бы нет. У вас ведь юнит-тесты последовательно исполняются, правильно? Обычно все так и делают, поэтому проблема и не вылазит. Точнее, не вылазит в разработке, а вот внедрение уже бывает бодрым и весёлым. :))
Цитата:
|
Кстати, а где об этом написано в документации?
|
В документации не написано просто потому, что не имеет смысла повторять учебник JavaScript. А вот в каких-нибудь вводных статьях может и упомянуто, но я их никогда не читал. :)
Цитата:
|
Ведь в блоке privates их объявлять нельзя получается. Только разве комментарий можно. А в конструкторе похоже можно создавать публичные свойства. Бардачок намечается чтоли?
|
Я вам страшную тайну открою: у объектов JavaScript вообще не бывает приватных свойств. То есть совсем. Ну, вот язык такой. Есть closures, но это не совсем то (точнее, совсем не то). А то, что в Ext JS классовая система поддерживает приватные методы, так это просто хак для облегчения нашей с вами жизни. И то больше нашей, чем вашей. :)
Практически единственный смысл блока privates - это дать вам, как пользователю, возможность узнать о том, что в вашем наследованном классе есть метод с таким же названием, как и приватный метод в родительском классе. В отличие от публичного API, приватные методы не гарантированы по прямой и обратной совместимости между версиями; т.е. мы оставляем себе право их менять как нам заблагорассудится. Мы слишком часто натыкались на ситуации, когда пользователи в своём коде называли методы так же, как и мы в своём. Результаты бывают феерически прекрасны, но очень трудоёмки к поимке.
Из этой проблемы и растут ноги у блока privates. Это наш способ дать вам знать: вот этот метод - он приватный, не трогайте его. А если потрогаете и ему не понравится, то мы не виноваты. :)
|
|
16.07.2015, 12:09
|
|
Профессор
|
|
Регистрация: 08.07.2013
Сообщений: 212
|
|
nohuhu,
я каждый раз когда ваши сообщения в разделе читаю, жалею что движок форума не разрешает одному человеку много плюсов ставить =)
|
|
16.07.2015, 13:06
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
Я вам страшную тайну открою: у объектов JavaScript вообще не бывает приватных свойств. То есть совсем.
|
Я наверное плохо донес... это свойство JS я в общем-то знаю. Просто я считал, что классовая система Ext исправила ситуацию.
Спасибо! Теперь есть чем заняться. Буду все написанные классы исправлять, там много у меня подобных свойств.
Цитата:
|
Подождите, а как вы предполагаете обойти базовые свойства языка в библиотеке? )
|
Мне сейчас придется начальные значения этих свойств описывать в конструкторе. По идее, классовая система Ext может это делать за меня, если в конфиге класса найдет такие свойства. Хотя бы так.
Но это не принципиально, просто заранее надо знать, что этот момент Ext не решает и надо самому не попасться.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
16.07.2015, 13:09
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Сообщение от Makarov
|
nohuhu,
я каждый раз когда ваши сообщения в разделе читаю, жалею что движок форума не разрешает одному человеку много плюсов ставить =)
|
Причем повторно выдать плюс не получается даже в случае, если перед этим оставил отзыв другому участнику.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
|
|