Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Странное поведение при работе с переменными протот 
V
    Опции темы
Megas
Дата 3.12.2012, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 15.1.2006

Репутация: нет
Всего: нет



Работая над одним проектом обнаружил для себя странное поведение при работе с переменными родительского класса.

Допустим у нас есть некий родительский класс:
Код

function ParentObj()
{
    this._some_arr = [];
    this._some_var = 5;

    this.pushArr = function(val)
    {
        this._some_arr.push(val);
    }

    this.getArr = function()
    {
        return this._some_arr;
    }

    this.setVal = function(val)
    {
        this._some_var = val;
    }

    this.getVal = function()
    {
        return this._some_var;
    }
}

Как видно у него две внутренние переменные: одно числовое, а другое массив. И пара функций для работы с каждой из переменных.

Теперь определим класс наследник:
Код

function ChildObj()
{
}

ChildObj.prototype = new ParentObj();


Я не гуру javascript'а, поэтому для меня было большим удивлением, что переменная-массив является общей для всех объектов класса ChildObj, в то время как вторая переменная каждая своя у каждого объекта.

Вот пример кода:
Код

var obj1 = new ChildObj;
var obj2 = new ChildObj;

obj1.pushArr(5);
obj1.setVal(11);

obj2.pushArr(8);
obj2.setVal(12);

console.log('Object 1 Array: '+ obj1.getArr().toString()); //Object 1 Array: 5,8
console.log('Object 1 Variable '+ obj1.getVal());              //Object 1 Variable 11
console.log('Object 2 Array: '+ obj2.getArr().toString()); //Object 2 Array: 5,8
console.log('Object 2 Variable '+ obj2.getVal());              //Object 2 Variable 12


Я прочитал много различных статей про ООП в javascript'е, но нигде не описывалась подобная проблема.
Ктото может объяснить почему такое происходит? Или дать ссылку на какуюто хорошую статью описывающую данную проблему?

И как эту проблему можно решить не прибегая к объявлении такой же переменной в классе наследника?
PM WWW   Вверх
Arantir
Дата 3.12.2012, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 14
Всего: 55



Цитата
И как эту проблему можно решить не прибегая к объявлении такой же переменной в классе наследника? 


Код

function ParentObj()
{
    this._some_arr = null;
    this._some_var = 5;
    this.pushArr = function(val)
    {
     if (this._some_arr == null)
         this._some_arr = new Array();
     this._some_arr.push(val);
    }
    this.getArr = function()
    {
        return this._some_arr;
    }
    this.setVal = function(val)
    {
        this._some_var = val;
    }
    this.getVal = function()
    {
        return this._some_var;
    }
}
function ChildObj()
{
}
ChildObj.prototype = new ParentObj();

var obj1 = new ChildObj;
var obj2 = new ChildObj;
obj1.pushArr(5);
obj1.setVal(11);
obj2.pushArr(8);
obj2.setVal(12);
console.log('Object 1 Array: '+ obj1.getArr().toString()); //Object 1 Array: 5
console.log('Object 1 Variable '+ obj1.getVal());              //Object 1 Variable 11
console.log('Object 2 Array: '+ obj2.getArr().toString()); //Object 2 Array: 8
console.log('Object 2 Variable '+ obj2.getVal());              //Object 2 Variable 12

О чем-то говорит? =)

Это сообщение отредактировал(а) Arantir - 3.12.2012, 13:31


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Megas
Дата 3.12.2012, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 15.1.2006

Репутация: нет
Всего: нет



Arantir, т.е. ты предлагаешь просто заменить массив на null? Это больше похоже на костыль, чем на нормальное решение. 

А почему это происходит, не вкурсе?
PM WWW   Вверх
baldina
Дата 3.12.2012, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 0
Всего: 101



Цитата(Megas @  3.12.2012,  13:05 Найти цитируемый пост)
что переменная-массив является общей для всех объектов класса ChildObj, в то время как вторая переменная каждая своя у каждого объекта.

"переменная-массив" тоже своя, только это не массив, а ссылка
PM MAIL   Вверх
CruorVult
Дата 3.12.2012, 15:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 868
Регистрация: 24.9.2008
Где: г.Киев, Украина

Репутация: 13
Всего: 28



Array(он же Object) - ссылочный тип, а String, Number - нет.
 
PM MAIL Skype   Вверх
Megas
Дата 3.12.2012, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 15.1.2006

Репутация: нет
Всего: нет



baldina, CruorVult, спасибо. Тоже уже догодался, что именно в этом дело.
PM WWW   Вверх
Arantir
Дата 3.12.2012, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 14
Всего: 55



Цитата(Megas @  3.12.2012,  14:29 Найти цитируемый пост)
Arantir, т.е. ты предлагаешь просто заменить массив на null? Это больше похоже на костыль, чем на нормальное решение. 
Нет!
Я предлагаю каждому потомку создавать собственный массив автоматически в родителе.
Можете поставить там ноль! Можете хоть поставить там "Hello world!"!
null просто не сбивает с толку, мол что это за число или что за строка.

Представьте себе, даже вот это работает:
Код

function ParentObj()
{
    this._some_arr = function() { };
    this._some_var = 5;
    this.pushArr = function(val)
    {
     if (typeof(this._some_arr) == "function")
         this._some_arr = new Array();
     this._some_arr.push(val);
    }
    this.getArr = function()
    {
        return this._some_arr;
    }
    this.setVal = function(val)
    {
        this._some_var = val;
    }
    this.getVal = function()
    {
        return this._some_var;
    }
}
А почему - уже объяснил CruorVult. Вы создаете свой массив (свою ссылку на отдельный массив) каждому потомку, а не используете ссылку на массив родителя.

При желании вы можете в родителе вписать в объявление даже готовый заполненный массив. Место объявления осталось одним-единственным. Но у каждого потомка будет свой независимый массив.

Где тут "костыль", не пойму никак... По-моему, это называется "отложенная инициализация". Ну ладно, я инициализировал ее в null. Но вы можете свободно оставить ее неинициализированной и проверять ее тип на undefined. Суть метода-то не в этом.

Это сообщение отредактировал(а) Arantir - 3.12.2012, 20:03


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
ksnk
Дата 3.12.2012, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 84
Всего: 386



Megas, Дело просто в другой схеме "наследования". Точнее - своей собственной, прототипной  smile 
В нормальной схеме есть класс - "разметка" будущего участка отведенных для объекта рессурсов под методы и атрибуты. а в прототипной - существует ссылка на другой объект - прототип.  Когда запрашивается атрибут от this, смещаемся по списку прототипов "вниз", а не лезем в несуществующую в JS таблицу классов. Некое просветление наступает, когда осознаешь, что прототипы можно менять на лету, тем самым получая себе доступ к свойствам самых странных объектов. 


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
CruorVult
Дата 4.12.2012, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 868
Регистрация: 24.9.2008
Где: г.Киев, Украина

Репутация: 13
Всего: 28



Я бы посоветовал почитать книжку Object-Oriented JavaScript By Stoyan Stefanov. Все вопросы сразу пропадут smile 
Там описано 12 способов наследования smile

Это сообщение отредактировал(а) CruorVult - 4.12.2012, 12:30
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.8379 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.