MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/d6d7ff2e2f9c

Learn web development

Объектно-ориентированный JavaScript для начинающих

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

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

Prerequisites: Basic computer literacy, a basic understanding of HTML and CSS, familiarity with JavaScript basics (see First steps and Building blocks) and OOJS basics (see Introduction to objects).
Objective: To understand the basic theory behind object-oriented programming, how this relates to JavaScript ("everything is an object"), and how to create constructors and object instances.

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

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

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

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

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

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

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

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

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

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

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

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

Это действительно полезно — преподаватели и студенты имеют много общих оособенностей, таких как имя, пол и возраст, и это удобно определить эти особенности только раз. Вы можете также задать одну и ту же характеристику отдельно в разных классах, как каждое определение этой характеристики будет в другом пространстве имен. Например, приветствие студента может быть в форме "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 использует другой механизм для совместного использования функциональных возможностей между объектами.

Note: Not being "classic OOP" is not necessarily a bad thing; as mentioned above, OOP can get very complex very quickly, and JavaScript has some nice ways to take advantage of OO features without having to get too deep into it.

Let's explore creating classes via constructors and creating object instances from them in JavaScript. First of all, we'd like you to make a new local copy of the oojs.html file we saw in our first Objects article.

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

  1. Let's start by looking at how you could define a person with a normal function. Add this function below the existing code:
    function createNewPerson(name) {
      var obj = {};
      obj.name = name;
      obj.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
      return obj;
    }
  2. You can now create a new person by calling this function — try the following lines in your browser's JavaScript console:
    var salva = createNewPerson('Salva');
    salva.name;
    salva.greeting();
    This works well enough, but it is a bit longwinded; if we know we want to create an object, why do we need to explicitly create a new empty object and return it? Fortunately JavaScript provides us with a handy shortcut, in the form of constructor functions — let's make one now!
  3. Replace your previous function with the following:
    function Person(name) {
      this.name = name;
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
    }

The constructor function is JavaScript's version of a class. You'll notice that it has all the features you'd expect in a function, although it doesn't return anything or explicitly create an object — it basically just defines properties and methods. You'll see the this keyword being used here as well — it is basically saying that whenever one of these object instances is created, the object's name property will be equal to the name value passed to the constructor call, and the greeting() method will use the name value passed to the constructor call too.

Note: A constructor function name usually starts with a capital letter — this convention is used to make constructor functions easier to recognize in code.

So how do we call a constructor to create some objects?

  1. Add the following lines below your previous code addition:
    var person1 = new Person('Bob');
    var person2 = new Person('Sarah');
  2. Save your code and reload it in the browser, and try entering the following lines into your text input:
    person1.name
    person1.greeting()
    person2.name
    person2.greeting()

Cool! You'll now see that we have two new objects on the page, each of which is stored under a different namespace — when you access their properties and methods, you have to start calls with person1 or person2; they are neatly packaged away so they won't clash with other functionality. They do however have the same name property and greeting() method available. Note that they are using their own name value that was assigned to them when they were created; this is one reason why it is very important to use this, so they will use their own values, and not some other value.

Let's look at the constructor calls again:

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

In each case, the new keyword is used to tell the browser we want to create a new object instance, followed by the function name with its required parameters contained in parentheses, and the result is stored in a variable — very similar to how a standard function is called. Each instance is created according to this definition:

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

After the new objects have been created, the person1 and person2 variables contain the following objects:

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

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

Note that when we are calling our constructor function we are defining greeting() every time, which isn't ideal. To avoid this we can define functions on the prototype instead, which we will look at later.

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

The example we looked at above was only a simple example to get us started. Let's now get on and create our final Person() constructor function.

  1. Remove the code you inserted so far, and add in this replacement constructor — this is exactly the same as the simple example in principle, with just a bit more complexity:
    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. Now add in the following line below it, to create an object instance from it:
    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

You'll now see that you can access the properties and methods just like we did with the first object we defined:

person1['age']
person1.interests[1]
person1.bio()
// etc.

Note: If you are having trouble getting this to work, try comparing your code against our version — see oojs-class-finished.html (also see it running live).

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

To start with, try adding a couple more object creation lines of your own, and try getting and setting the members of the resulting object instances.

In addition, there are a couple of problems with our bio() method — the output always includes the pronoun "He", even if your person is female, or some other preferred gender classification. And the bio will only include two interests, even if more are listed in the interests array. Can you work out how to fix this in the class definition (constructor)? You can put any code you like inside a constructor (you'll probably need a few conditionals and a loop). Think about how the sentences should be structured differently depending on gender, and depending on whether the number of listed interests is 1, 2, or more than 2.

Note: If you get stuck, we have provided an answer inside our GitHub repo (see it live) — try writing it yourself first though!

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

So far we've seen two different ways to create an object instance — declaring an object literal, and using a constructor function (see above).

These make sense, but there are other ways — we want to make you familiar with these in case you come across them in your travels around the Web.

The Object() constructor

First of all, you can use the Object() constructor to create a new object. Yes, even generic objects have a constructor, which generates an empty object.

  1. Try entering this into your browser's JavaScript console:
    var person1 = new Object();
  2. This stores an empty object in the person1 variable. You can then add properties and methods to this object using dot or bracket notation as desired; try these examples:
    person1.name = 'Chris';
    person1['age'] = 38;
    person1.greeting = function() {
      alert('Hi! I\'m ' + this.name + '.');
    };
  3. You can also pass an object literal to the Object() constructor as a parameter, to prefill it with properties/methods. Try this:
    var person1 = new Object({
      name: 'Chris',
      age: 38,
      greeting: function() {
        alert('Hi! I\'m ' + this.name + '.');
      }
    });

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

JavaScript has a built-in method called create(), which allows you to create a new object instance based on an existing object.

  1. Try this in your JavaScript console:
    var person2 = Object.create(person1);
  2. Now try these:
    person2.name
    person2.greeting()

You'll see that person2 has been created based on person1 — it has the same properties and method available to it. This is pretty useful, as it allows you to create new object instances without needing to define a constructor. The downside is that create() is not supported by browsers as far back as constructors (IE9, as opposed to IE8 or even before), plus some think constructors give your code more order — you can create your constructors in one place, then create instances as needed, and it is clear where they came from.

However, if you are not too worried about supporting really old browsers, and you only need a couple of copies of an object, creating a constructor could be overkill for your code. It is up to you what you prefer. Some people simply find create() easier to understand and use.

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

Сводка

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

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

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

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