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

Разобравшись с основами, сосредоточимся на объектно-ориентированном JavaScript (OOJS) — в данной статье представлены базовые возможности теории объектно-ориентированного программирования (ООП), затем рассмотрено как в JavaScript эмулировать классы объектов с помощью функции-конструктора и как создать экземпляры объектов.

Предпосылки: Базовая компьютерная грамотность, базовое понимание HTML и CSS, знакомство с основами JavaScript (см. Первые шаги and Строительные блоки) и основы OOJS (см. Введение в объекты).
Задача: Чтобы понять основную теорию объектно-ориентированного программирования, как это относится к JavaScript («все является объектом») и как создавать конструкторы и экземпляры объектов.

Объектно-ориентированное программирование с высоты 10,000 метров

Давайте начнём с упрощенного, высокоуровневого представления об объектно-ориентированном программировании (ООП). Мы говорим упрощенно, потому что ООП может быстро стать очень сложным, и если сейчас дать полный курс, вероятно, можно запутать больше, чем помочь. Основная идея ООП заключается в том, что мы используем объекты в модели реального мира, которую мы хотим представить в нашей программе и/или обеспечить простой способ доступа к функциям, которые в противном случае было бы трудно или невозможно использовать.

Объекты могут содержать данные и код, которые представляют информацию о том, что вы пытаетесь смоделировать, и функциональные возможности или поведение, которое вы хотите иметь. Данные объекта (и, чаще всего, функции тоже) могут быть точно сохранены (официальный термин "инкапсулированы") внутри пакета объекта (которому может быть дано определенное название для обозначения, которое иногда называют пространством имен), упрощая структуру и доступ; объекты также широко используются в качестве хранилищ данных, которые могут быть легко отправлены по сети.

Определение шаблона объекта

Рассмотрим простую программу, которая отображает информацию об учащихся и учителях в школе. Здесь мы рассмотрим теорию ООП в целом, не в контексте какого-либо конкретного языка программирования.

Чтобы начать, вернёмся к объекту Person из нашей статьи Основы объектов, который определяет Общие сведения и функциональные возможности человека. Есть много вещей, которые вы можете узнать о человеке (его адрес, рост, размер обуви, профиль ДНК, номер паспорта, значимые черты личности ...) , но в данном случае нас интересует только имя, возраст, пол и интересы, и мы также хотим быть в состоянии написать краткую информацию о нём, основываясь на этих данных, и получать их, чтобы поприветствовать. Это известно как abstraction — создание простой модели более сложной сущности, которая представляет её наиболее важные аспекты таким образом, чтобы было удобно работать для выполнения целей нашей программы.

В некоторых языках ООП, это общее определение типа объекта называется class (JavaScript использует другой механизм и терминологию, как вы увидите ниже) — это на самом деле не объект, а шаблон, который определяет, какие характеристики должен иметь объект.

Создание реальных объектов

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

Когда экземпляр объекта создается из класса, для его создания выполняется функция-конструктор класса. Этот процесс создания экземпляра объекта из класса называется создание экземпляра — из класса создается экземпляр объекта.

Специализированные классы

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

Это действительно полезно — преподаватели и студенты имеют много общих особенностей, таких как имя, пол и возраст, и удобно определить эти особенности только один раз. Вы можете также задать одну и ту же характеристику отдельно в разных классах, как каждое определение этой характеристики будет в другом пространстве имен. Например, приветствие студента может быть в форме "Yo, I'm [firstName]" (например Yo, I'm Sam), в то время как учитель может использовать что-то более формальное, такое как "Hello, my name is [Prefix] [lastName], and I teach [Subject]." (например Hello, My name is Mr Griffiths, and I teach Chemistry).

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

Теперь вы можете создавать экземпляры объекта из дочерних классов. Например:

Далее мы рассмотрим, как ООП теорию можно применить на практике в JavaScript.

Конструкторы и экземпляры объектов

Некоторые люди утверждают, что JavaScript - это не настоящий объектно-ориентированный язык — например, он не имеет объявления class  для создания классов, как многие ОО языки. Вместо этого в JavaScript используются специальные функции, называемые constructor functions для определения объектов и их особенностей. Они полезны, так как часто встречаются ситуации, в которых не известно, сколько объектов будет создано; конструкторы позволяют создать столько объектов, сколько нужно эффективным способом, прикреплением данных и функций для объектов по мере необходимости.

Когда новый экземпляр объекта создается с помощью функции-конструктора, функциональность не в том, что все копируются в новый объект как в "классических" ОО-языках — вместо этого функциональность в связи через ссылку цепи называемой цепочкой прототипов (см. Object prototypes). Так что это неправильное заявление, строго говоря - JavaScript использует другой механизм для совместного использования функциональных возможностей между объектами.

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

Простой пример

  1. Начнем с того, что вы можете определить человека с нормальной функцией. Добавьте эту функцию в элемент script:
    function createNewPerson(name) {
      var obj = {};
      obj.name = name;
      obj.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
      return obj;
    }
  2. Теперь вы можете создать нового человека, вызвав эту функцию - попробуйте следующие строки в консоли JavaScript браузера:
    var salva = createNewPerson('Salva');
    salva.name;
    salva.greeting();
    Это работает достаточно хорошо, но это немного затянуто; если мы знаем, что хотим создать объект, зачем нам явно создавать новый пустой объект и возвращать его? К счастью, JavaScript предоставляет нам удобный ярлык в виде функций-конструкторов - давайте сделаем это сейчас!
  3. Замените предыдущую функцию следующей:
    function Person(name) {
      this.name = name;
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
    }

Функция-конструктор - это версия класса JavaScript. Вы заметите, что в нем есть все функции, которые вы ожидаете от функции, хотя они ничего не возвращают или явно не создают объект - он в основном определяет свойства и методы. Вы также увидите, что ключевое слово thisиспользуется здесь, - в основном это говорит о том, что всякий раз, когда создается один из этих экземпляров объектов, свойство имени объекта будет равно значению name, переданному вызову конструктора, и метод greeting() будет использовать значение имени, переданное также вызову конструктора.

Примечание: Имя функции конструктора обычно начинается с заглавной буквы - это соглашение используется для упрощения распознавания функций конструктора в коде.

Итак, как мы называем конструктор для создания некоторых объектов?

  1. Добавьте следующие строки ниже вашего предыдущего добавления кода:
    var person1 = new Person('Bob');
    var person2 = new Person('Sarah');
  2. Сохраните код и перезагрузите его в браузере и попробуйте ввести следующие строки в консоль JS:
    person1.name
    person1.greeting()
    person2.name
    person2.greeting()

Круто! Теперь вы увидите, что у нас есть два новых объекта на странице, каждый из которых хранится в другом пространстве имен - при доступе к их свойствам и методам вы должны запускать вызовы с person1 или person2; содержащаяся внутри, аккуратно упакована, поэтому она не будет сталкиваться с другими функциями. Тем не менее, у них есть одно и то же свойство name и greeting(). Обратите внимание, что они используют свое собственное name, которое было присвоено им, когда они были созданы; это одна из причин, почему очень важно использовать это, поэтому они будут использовать свои собственные значения, а не какое-то другое значение.

Давайте снова посмотрим на вызовы конструктора:

var person1 = new Person('Bob');
var person2 = new Person('Sarah');

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

function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

После создания новых объектов переменные person1 и person2 содержат следующие объекты:

{
  name: 'Bob',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

{
  name: 'Sarah',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

Обратите внимание, что когда мы вызываем нашу конструкторскую функцию, мы определяем greeting() каждый раз, что не является идеальным. Чтобы этого избежать, вместо этого мы можем определить функции на прототипе, о которых мы поговорим позже.

Создавая наш готовый конструктор

Пример, на который мы смотрели выше, был только простым примером, чтобы мы начали. Давайте теперь займемся и создадим нашу конечную функцию конструктора Person().

  1. Удалите введенный код до сих пор и добавьте в этот конструктор замены - это точно так же, как простой пример в принципе, с чуть большей сложностью:
    function Person(first, last, age, gender, interests) {
      this.name = {
        first,
        last
      };
      this.age = age;
      this.gender = gender;
      this.interests = interests;
      this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
      };
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
      };
    };
  2. Теперь добавьте следующую строку ниже, чтобы создать экземпляр объекта из него:
    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

Теперь вы увидите, что вы можете получить доступ к свойствам и методам, как это было ранее, - попробуйте использовать их в консоли JS:

person1['age']
person1.interests[1]
person1.bio()
// etc.
Примечание: Если у вас возникли проблемы с его работой, попробуйте сравнить код с нашей версией - см. oojs-class-finished.html (также смотрите, как он работает в прямом эфире).

Дальнейшие упражнения

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

Кроме того, есть несколько проблем с нашим методом bio() - вывод всегда включает местоимение «Он», даже если ваш человек является женщиной или какой-либо другой предпочтительной гендерной классификацией. И био будет включать только два интереса, даже если в массиве interests указано больше. Можете ли вы решить, как исправить это в определении класса (конструкторе)? Вы можете поместить любой код, который вам нравится внутри конструктора (вам, вероятно, понадобятся несколько условностей и цикл). Подумайте о том, как предложения должны быть структурированы по-разному в зависимости от пола и в зависимости от того, имеет ли число перечисленных интересов 1, 2 или более 2.

Примечание: Если Вы застряли, мы предоставили ответ в нашем репозитории GitHub (см. это в действии) — но сначала попробуйте написать сами!

Другие способы создания экземпляров объектов

До сих пор мы видели два разных способа создания экземпляра объекта - объявление объектного литерала и использование функции конструктора (см. выше).

Это имеет смысл, но есть и другие способы - мы хотим, чтобы вы были знакомы с ними, если вы встретите их в своих путешествиях по Сети.

Конструктор Object ()

Прежде всего, вы можете использовать конструктор Object() для создания нового объекта. Да, даже общие объекты имеют конструктор, который генерирует пустой объект.

  1. Попробуйте ввести это в консоль JavaScript вашего браузера:
    var person1 = new Object();
  2. Это сохраняет пустой объект в переменной person1. Затем вы можете добавить свойства и методы к этому объекту с использованием точечной или скобочной нотации по желанию; попробуйте эти примеры в консоли:
    person1.name = 'Chris';
    person1['age'] = 38;
    person1.greeting = function() {
      alert('Hi! I\'m ' + this.name + '.');
    };
  3. Вы также можете передать литерал объекта конструктору Object() в качестве параметра, чтобы заполнить его свойствами / методами. Попробуйте это в консоли JS:
    var person1 = new Object({
      name: 'Chris',
      age: 38,
      greeting: function() {
        alert('Hi! I\'m ' + this.name + '.');
      }
    });

Использование метода create()

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

Однако некоторые люди предпочитают создавать экземпляры объектов без предварительного создания конструкторов, особенно если они создают только несколько экземпляров объекта. JavaScript имеет встроенный метод create(), который позволяет вам это делать. С его помощью вы можете создать новый объект на основе любого существующего объекта.

  1. Когда вы закончили упражнение из предыдущих разделов, загруженных в браузер, попробуйте это в консоли JavaScript:
    var person2 = Object.create(person1);
  2. Теперь попробуйте:
    person2.name
    person2.greeting()

Вы увидите, что person2 был создан на основе person1 - он имеет те же свойства и метод, доступные для него.

Одно ограничение create() заключается в том, что IE8 не поддерживает его. Поэтому конструкторы могут быть более эффективными, если вы хотите поддерживать старые браузеры.

мы исследуем эффекты create()более подробно.

Сводка

В данной статье представлено упрощенное представление объектно-ориентированной теории — и это не полная история, но представление о том, с чем мы имеем дело. В дополнение, мы начали рассматривать, как JavaScript относится к "классическому ООП" и чем он отличается от него, как реализовать классы в JavaScript с помощью функции конструктора, и разные способы создания экземпляров объектов.

В следующей статье мы рассмотрим прототипы объектов JavaScript.

Метки документа и участники

Внесли вклад в эту страницу: sergeomak, Elena_Petrenko, uandrew, slychai85, superpuper32, GennadyGlushenkov
Обновлялась последний раз: sergeomak,