Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 15.07.2015, 17:50
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #2 (permalink)  
Старый 15.07.2015, 18:28
Профессор
Отправить личное сообщение для novikov Посмотреть профиль Найти все сообщения от novikov
 
Регистрация: 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.
Ответить с цитированием
  #3 (permalink)  
Старый 15.07.2015, 18:37
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #4 (permalink)  
Старый 15.07.2015, 21:14
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 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 это конфигурационное свойство. Использовать и те и другие в одном объекте это совершенно обычное дело, надо просто понимать разницу.
Ответить с цитированием
  #5 (permalink)  
Старый 15.07.2015, 21:26
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #6 (permalink)  
Старый 15.07.2015, 21:32
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

Кстати, в свете новых сведений о создании свойств не ясно как создавать приватные свойства.

Ext.define(..., {

privates: {...}

});


Ведь в блоке privates их объявлять нельзя получается. Только разве комментарий можно. А в конструкторе похоже можно создавать публичные свойства. Бардачок намечается чтоли?
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
  #7 (permalink)  
Старый 15.07.2015, 23:57
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 21.05.2015
Сообщений: 321

Сообщение от khusamov Посмотреть сообщение
Не понятно как система классов Ext JS допустила эту странную ситуацию. Зачем такое может вообще понадобиться? Чтобы иметь доступ к общему массиву (или что там будет вложено в свойство).
Подождите, а как вы предполагаете обойти базовые свойства языка в библиотеке? :))

Цитата:
На мой взгляд не совсем логично, что свойства надо создавать в конструкторе (точнее с точки зрения JS нормально, но с точки зрения обычного ООП не привычно, а ведь Ext JS пытается имитировать обычный ООП). И если забудешь создать, то будет ссылка на общее значение.
Ну, вот такой вот язык этот JavaScript. Выбора какбэ нет, скорбь и пичалька.

Цитата:
Кстати, я до сих пор не сталкивался с этой проблемой, а ведь уже сколько подобных свойств я насоздавал и пока не напарывался... Придется всю толпу классов перерыть и всюду сделать инициализацию в конструкторе... неслабо однако…
Большая часть таких конструкций может работать просто по случайности, как оно обычно и бывает. Если не создаёте более одного экземпляра класса одновременно, то и проблем как будто бы нет. У вас ведь юнит-тесты последовательно исполняются, правильно? Обычно все так и делают, поэтому проблема и не вылазит. Точнее, не вылазит в разработке, а вот внедрение уже бывает бодрым и весёлым. :))

Цитата:
Кстати, а где об этом написано в документации?
В документации не написано просто потому, что не имеет смысла повторять учебник JavaScript. А вот в каких-нибудь вводных статьях может и упомянуто, но я их никогда не читал. :)

Цитата:
Ведь в блоке privates их объявлять нельзя получается. Только разве комментарий можно. А в конструкторе похоже можно создавать публичные свойства. Бардачок намечается чтоли?
Я вам страшную тайну открою: у объектов JavaScript вообще не бывает приватных свойств. То есть совсем. Ну, вот язык такой. Есть closures, но это не совсем то (точнее, совсем не то). А то, что в Ext JS классовая система поддерживает приватные методы, так это просто хак для облегчения нашей с вами жизни. И то больше нашей, чем вашей. :)

Практически единственный смысл блока privates - это дать вам, как пользователю, возможность узнать о том, что в вашем наследованном классе есть метод с таким же названием, как и приватный метод в родительском классе. В отличие от публичного API, приватные методы не гарантированы по прямой и обратной совместимости между версиями; т.е. мы оставляем себе право их менять как нам заблагорассудится. Мы слишком часто натыкались на ситуации, когда пользователи в своём коде называли методы так же, как и мы в своём. Результаты бывают феерически прекрасны, но очень трудоёмки к поимке.

Из этой проблемы и растут ноги у блока privates. Это наш способ дать вам знать: вот этот метод - он приватный, не трогайте его. А если потрогаете и ему не понравится, то мы не виноваты. :)
Ответить с цитированием
  #8 (permalink)  
Старый 16.07.2015, 12:09
Аватар для Makarov
Профессор
Отправить личное сообщение для Makarov Посмотреть профиль Найти все сообщения от Makarov
 
Регистрация: 08.07.2013
Сообщений: 212

nohuhu,
я каждый раз когда ваши сообщения в разделе читаю, жалею что движок форума не разрешает одному человеку много плюсов ставить =)
Ответить с цитированием
  #9 (permalink)  
Старый 16.07.2015, 13:06
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

Цитата:
Я вам страшную тайну открою: у объектов JavaScript вообще не бывает приватных свойств. То есть совсем.
Я наверное плохо донес... это свойство JS я в общем-то знаю. Просто я считал, что классовая система Ext исправила ситуацию.

Спасибо! Теперь есть чем заняться. Буду все написанные классы исправлять, там много у меня подобных свойств.

Цитата:
Подождите, а как вы предполагаете обойти базовые свойства языка в библиотеке? )
Мне сейчас придется начальные значения этих свойств описывать в конструкторе. По идее, классовая система Ext может это делать за меня, если в конфиге класса найдет такие свойства. Хотя бы так.

Но это не принципиально, просто заранее надо знать, что этот момент Ext не решает и надо самому не попасться.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
  #10 (permalink)  
Старый 16.07.2015, 13:09
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

Сообщение от Makarov Посмотреть сообщение
nohuhu,
я каждый раз когда ваши сообщения в разделе читаю, жалею что движок форума не разрешает одному человеку много плюсов ставить =)
Причем повторно выдать плюс не получается даже в случае, если перед этим оставил отзыв другому участнику.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
узнать css значения класса winch jQuery 10 02.05.2015 22:45