§08. Конструкторы. Массив объектов. Простейшая база данных.

Учимся программировать вместе с JavaScript
Глава I. Обо всём понемногу.

§08. Конструкторы. Массив объектов. Простейшая база данных.

Конструкторы. Создание свойства типа объект с помощью конструктора. Массив объектов. Массив объектов как свойство объекта. Создание методов в конструкторе. Простейшая база данных.

Конструкторы. 

В предыдущем параграфе мы научились создавать объекты в единственном экземпляре. На практике существует масса случаев, когда необходимо создавать множество одинаковых объектов. Для того, что бы не повторять один и тот же код, существуют конструкторы, с помощью которых можно создавать одинаковые объекты. 

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

Далее пример конструктора, который создаёт объект birthday, как в предыдущем параграфе: 

 

function Birthday() 

{ 

  this.day; 

  this.month; 

  this.year; 

} 

 

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

Теперь обратите внимание на новое для вас слово this. Что бы не забивать себе голову, скажем так: это слово в данной ситуации заменяет имя объекта, которого ещё не существует. Если после него поставить точку и указать имя, то будет создано свойство с этим именем. 

Как было уже сказано конструктор помимо создания объекта, может инициализировать его свойства. Делается это следующим образом: 

 

function Birthday() 

{ 

  this.day = 30; 

  this.month = 'октябрь'; 

  this.year = 2004; 

} 

 

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

 

function Birthday(d,m,y) 

{ 

  this.day = d; 

  this.month = m; 

  this.year = y; 

} 

 

 Сейчас будьте внимательны. Для создания объекта в коде программы с помощью конструктора используется слово new. Без него объект создан не будет. Пример: 

 

var birthday_1 = new Birthday(30,'октябрь',2004); 

var birthday_2 = new Birthday(28,'январь',2005); 

 

Думаю, что на данном этапе нет смысла вдаваться в подробности и уточнять, что такое слово new. Просто знайте, что для создания объекта необходимо его написать, после чего вызвать функцию конструктор. В результате мы получим объект, который будет присвоен переменной, которая стоит слева от знака равно. 

Созданный таким образом объект ничем не отличается от тех, которые были созданы в предыдущем параграфе. Далее пример, в котором созданы два объекта birthday_1 и birthday_2, а так же осуществлён доступ к их свойствам: 

 

<script> 

function Birthday(d,m,y) 

{ 

  this.day = d; 

  this.month = m; 

  this.year = y; 

} 

 

var birthday_1 = new Birthday(30,'октябрь',2004); 

var birthday_2 = new Birthday(28,'январь',2005); 

 

document.write('Первая дата рождения: ' 

         ,birthday_1.day,' ',birthday_1.month,' ', 

         birthday_1.year,'г.<br>'); 

 

document.write('Вторая дата рождения: ' 

         ,birthday_2.day,' ',birthday_2.month,' ', 

         birthday_2.year,'г.<br>'); 

 

</script> 

 

 

Создание свойства типа объект с помощью конструктора. 

С помощью слова new и конструктора можно так же создавать свойства типа объект внутри другого конструктора. Для примера создадим конструктор Pupil, который будет создавать такой же объект pupil как в предыдущем параграфе: 

 

<script> 

function Birthday(d,m,y) 

{ 

  this.day = d; 

  this.month = m; 

  this.year = y; 

} 

 

function Pupil(SN,N,A,d,m,y) 

{ 

  this.surname = SN; 

  this.name = N; 

  this.age = A; 

  this.birthday = new Birthday(d,m,y); 

} 

 

var pupil_1 = new Pupil('Куклин','Денис',12,30,'октябрь',2004); 

var pupil_2 = new Pupil('Иванов','Петр',11,28,'январь',2005); 

 

document.write('Первый ученик: ', 

          pupil_1.surname,' ',pupil_1.name,'. ', 

          pupil_1.age,' лет. Родился ', 

         pupil_1.birthday.day,' ',pupil_1.birthday.month,' ', 

         pupil_1.birthday.year,'г.<br>'); 

 

document.write('Второй ученик: ', 

          pupil_2.surname,' ',pupil_2.name,'. ', 

          pupil_2.age,' лет. Родился ', 

         pupil_2.birthday.day,' ',pupil_2.birthday.month,' ', 

         pupil_2.birthday.year,'г.<br>'); 

 

</script> 

 

 

Обратите внимание на 14 строчку, она выделена жирным шрифтом. Как раз в ней происходит создание свойства типа объект с помощью конструктора. 

Так же обратите внимание на то, что доступ к свойствам свойства birthday происходит с помощью второй точки. 

 

Массив объектов. 

Как было уже сказано, массив может содержать в себе элементы любого типа. Это утверждение относится и к объектам. Т.е. можно создавать массив объектов. 

Для создания элемента массива типа число или типа строка мы просто присваивали новому элементу значение. В случае с элементом типа объект дела обстоят несколько сложнее. Для его создания обязательно нужно использовать конструктор. Пример: 

 

var pupils = []; 

pupils[0] = new Pupil('Куклин','Денис',12,30,'октябрь',2004); 

pupils[1] = new Pupil('Иванов','Петр',11,28,'январь',2005); 

 

Примечание: если мы попытаемся элементу массива присвоить переменную типа объект, то в итоге получим, что в элементе массива будет содержаться ссылка на эту переменную, а не объект. О том, что такое ссылки мы узнаем позже. 

 

Доступ к свойствам элементов массива осуществляется так же с помощью точек. Пример: 

 

document.write('Элемент массива 0: ', 

          pupils[0].surname,' ',pupils[0].name,'. ', 

          pupils[0].age,' лет. Родился ', 

         pupils[0].birthday.day,' ',pupils[0].birthday.month,' ', 

         pupils[0].birthday.year,'г.<br>'); 

 

document.write('Элемент массива 1: ', 

          pupils[1].surname,' ',pupils[1].name,'. ', 

          pupils[1].age,' лет. Родился ', 

         pupils[1].birthday.day,' ',pupils[1].birthday.month,' ', 

         pupils[1].birthday.year,'г.<br>'); 

 

 

Массив объектов как свойство объекта. 

В качестве свойства любого объекта может быть массив любых значений, в том числе и объектов. Для примера создадим объект  clas, у которого будет свойство pupils, содержащее в себе массив учеников. 

Примечание: объект clas напишем с одной буквой s т.к. слово class является зарезервированным, и мы не можем его использовать в качестве имёни. 

Пример: 

 

var clas 

 

  pupils: 

  [ 

    new Pupil('Куклин','Денис',12,30,'октябрь',2004), 

    new Pupil('Иванов','Петр',11,28,'январь',2005) 

  ] 

}; 

 

document.write('Первый ученик в классе: ', 

          clas.pupils[0].surname,' ', 

          clas.pupils[0].name,'. ', 

          clas.pupils[0].age,' лет. Родился ', 

         clas.pupils[0].birthday.day,' ', 

         clas.pupils[0].birthday.month,' ', 

         clas.pupils[0].birthday.year,'г.<br>'); 

 

document.write('Второй ученик в классе: ', 

          clas.pupils[1].surname,' ', 

          clas.pupils[1].name,'. ', 

          clas.pupils[1].age,' лет. Родился ', 

         clas.pupils[1].birthday.day,' ', 

         clas.pupils[1].birthday.month,' ', 

         clas.pupils[1].birthday.year,'г.<br>'); 

 

 

Обратите внимание на то, каким образом происходит доступ к свойствам элементов свойства pupils. Так же как и в случае с обычным массивом, в квадратных скобках указывается индекс. 

 

Создание методов в конструкторе. 

В конструкторе помимо свойств можно создавать и методы. Для примера, напишем конструктор  Clas, который будет создавать такой же объект, как в предыдущем примере, но с методом print, который будет выводить информацию об ученике по его индексу: 

 

function Clas() 

{ 

  this.pupils 

  [ 

    new Pupil('Куклин','Денис',12,30,'октябрь',2004), 

    new Pupil('Иванов','Петр',11,28,'январь',2005) 

  ]; 

  this.print = function(i) 

  { 

     document.write(i+1,' ученик в классе: ', 

             clas.pupils[i].surname,' ', 

             clas.pupils[i].name,'. ', 

             clas.pupils[i].age,' лет. Родился ', 

            clas.pupils[i].birthday.day,' ', 

            clas.pupils[i].birthday.month,' ', 

            clas.pupils[i].birthday.year,'г.<br>'); 

  }; 

} 

 

var clas = new Clas(); 

 

clas.print(0); 

clas.print(1); 

 

 

Примечание: строчки, в которых был создан метод print, выделены жирным шрифтом. Обратите внимание на то, что в конструкторе метод создаётся так же с помощью слова this. Так же на то, каким образом производится вызов метода уже в коде программы.  

 

Простейшая база данных. 

Объекты и массивы являются очень важными аспектами в программировании. Поэтому необходимо основательно усвоить пройденный материал. Для этого на основе уже созданных нами объектов создадим базу данных учеников в классе. 

Прежде чем приступить непосредственно к программированию опишем словесно, что у нас должно получиться. 

Во-первых, база данных это совокупность данных, которая может быть обработана компьютером. В нашем случае этой совокупностью может стать массив учеников, который содержит в себе фамилию, имя, возраст и дату рождения. 

Во-вторых, нам необходимо будет нашу базу данных обрабатывать, т.е. сортировать учеников по фамилии, по имени, по возрасту и дате рождения. А так же выводить данные в виде таблиц. Совокупность программ, обрабатывающих базу данных называется системой управления базой данных (СУБД). Т.е. нам понадобится и СУБД. На практике для её создания мы напишем ряд функций сортирующих и выводящих данные. 

Для того, что бы соблюсти принципы ООП, мы должны совместить базу данных и СУБД в одном объекте. На самом деле это очень удобно, т.к. написав конструктор для создания одного объекта, мы сможем создавать любое количество различных классов учеников. 

Подведя итог вышесказанному перечислим, что мы должны сделать. Необходимо создать конструктор Clas, который будет создавать объект со свойством pupils, которое является массивом объектов pupil, и методами, которые будут сортировать и выводить данные об учениках в виде таблиц. Так же необходим метод поиска ученика по фамилии.  

Так же необходимо написать программу демонстрирующую работу получившегося объекта. 

Далее пример, в котором создан с помощью конструктора объект clas. Данный объект имеет свойство массив с учениками, метод вывода учеников в виде таблицы и метод сортировки учеников по фамилии. Создать методы сортировки по имени и возрасту, а так же метод поиска ученика по фамилии будет предложено в задаче для самостоятельной работы. 

 

<script> 

function Birthday(d,m,y)//Конструктор 

{ 

  this.day = d; 

  this.month = m; 

  this.year = y; 

} 

 

function Pupil(SN,N,A,d,m,y)//Конструктор 

{ 

  this.surname = SN; 

  this.name = N; 

  this.age = A; 

  this.birthday = new Birthday(d,m,y); 

} 

 

function Clas()//Конструктор 

{ 

  this.size = 10;//количество учеников 

  this.pupils //массив учеников 

  [ 

    new Pupil('Куклин','Денис',12,30,'октябрь',2004), 

    new Pupil('Сидоров','Владислав',12,2,'ноябрь',2004), 

    new Pupil('Овечкин','Егор',12,15,'декабрь',2004), 

    new Pupil('Илюхин','Антон',12,2,'сеньябрь',2004), 

    new Pupil('Петров','Петр',12,22,'октябрь',2004), 

    new Pupil('Никулин','Юрий',11,2,'февраль',2005), 

    new Pupil('Дроздов','Эдуард',12,30,'сеньябрь',2004), 

    new Pupil('Бобров','Иван',11,6,'март',2005), 

    new Pupil('Перескоков','Денис',12,31,'октябрь',2004), 

    new Pupil('Иванов','Петр',11,28,'январь',2005) 

  ]; 

  this.print_table = function()//Выводит таблицу с учениками 

  { 

    document.write('<table border = "1">'); 

    document.write('<tr><td><b>Фамилия</b></td>', 

                   '<td><b>Имя</b></td>', 

                   '<td><b>Возраст</b></td>', 

                   '<td><b>Дата рождения</b></td></tr>'); 

    for (var c = 0;c<this.size; c=c+1) 

      document.write('<tr><td>',clas.pupils[c].surname, 

                '</td><td>',clas.pupils[c].name, 

                '</td><td>',clas.pupils[c].age, 

                '</td><td>',clas.pupils[c].birthday.day,' ', 

                clas.pupils[c].birthday.month,' ', 

                clas.pupils[c].birthday.year,'г.</td></tr>'); 

    document.write('</table>'); 

  } 

  this.sort_S = function()//Сортирует по фамилии 

  { 

    var b;//Индикатор отсортированности 

    do { 

      b = 0;//Обнуляем переменную 

      for (var c = 0; c < (this.size-1); c = c+1) 

      { 

        //Если элемент больше следующего 

        if (this.pupils[c].surname > this.pupils[c+1].surname 

        { 

          b = 1; 

        //Меняем элементы местами 

          var temp = new Pupil('','',0,0,'',0); 

          temp = this.pupils[c]; 

          this.pupils[c] = this.pupils[c+1]; 

          this.pupils[c+1] = temp; 

        } 

      } 

    } while (b>0) 

  } 

} 

 

var clas = new Clas(); 

 

document.write('База данных в первоначальном виде:<br>'); 

clas.print_table(); 

clas.sort_S(); 

document.write('<br>После сортировки по фамилии:<br>'); 

clas.print_table(); 

 

</script> 

 

Обратите особое внимание на метод sort_S, который сортирует массив учеников по фамилии. Для перемены местами элементов массива была создана переменная temp. Создана она была с помощью конструктора Pupil. Если просто создать переменную и присвоить ей значение типа объект, то переменная сохранит ссылку на этот объект, но не сам объект. Поэтому и был использован конструктор. 

Если обрисовать данную ситуацию другими словами то получится следующее: для того, что бы переменная могла содержать в себе значение типа объект, необходимо использовать конструктор, который в памяти компьютера выделит место для хранения свойств и методов. 

 

Примечание: в данном примере свойство массив pupils было заполнено прямо в конструкторе Clas. При таком заполнении конструктор Clas будет создавать объекты с одинаковыми учениками. На практике заполнять массив учеников можно автоматически из html документа, либо из полей заполняемых пользователем. Пока делать это мы не умеем. Поэтому конструктор Clas был написан именно таким образом. 

 

 Задачи. 

1. Создать методы сортировки по имени и возрасту, а так же метод поиска ученика по фамилии. Продемонстрировать их работу. 

2. Добавить в базу данных таблицу с оценками по различным предметам. Для этого создать массив объектов оценок. Причём индекс ученика в  массиве объектов учеников должен соответствовать индексу в массиве объектов оценок. Создать метод, вычисляющий средний бал у каждого ученика. Создать метод, сортирующий оба массива по среднему балу. Метод, выводящий таблицу с оценками: фамилия, оценки по предметам и средний бал. И метод выводящий таблицу с данными учеников и средний бал за оценки по предметам. Создать метод поиска ученика с наивысшим средним балом. Создать методы вывода троечников, ударников и отличников по среднему баллу.