From 74f1c3c85cf4f0ff1cc631d1320ed90c404c6ed7 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Sun, 11 Jul 2021 13:02:49 -0400 Subject: delete conflicting/orphaned docs in ru (#1426) --- .../learn/javascript/objects/index.html | 357 --------------------- 1 file changed, 357 deletions(-) delete mode 100644 files/ru/conflicting/learn/javascript/objects/index.html (limited to 'files/ru/conflicting/learn/javascript/objects') diff --git a/files/ru/conflicting/learn/javascript/objects/index.html b/files/ru/conflicting/learn/javascript/objects/index.html deleted file mode 100644 index c1a92d8c1d..0000000000 --- a/files/ru/conflicting/learn/javascript/objects/index.html +++ /dev/null @@ -1,357 +0,0 @@ ---- -title: Вступление в Объектно-ориентированный JavaScript -slug: conflicting/Learn/JavaScript/Objects -translation_of: Learn/JavaScript/Objects -translation_of_original: Web/JavaScript/Introduction_to_Object-Oriented_JavaScript -original_slug: Web/JavaScript/Introduction_to_Object-Oriented_JavaScript ---- -

Объектно-ориентированный до основания, JavaScript предоставляет мощные и гибкие {{Glossary("OOP")}} возможности. Эта статья начинается с введения в объектно-ориентированное программирование, затем рассматривает модель объекта JavaScript и, наконец, демонстрирует концепции объектно-ориентированного программирования в JavaScript.

- -

Обзор JavaScript

- -

Если вы неуверенно владеете такими концепциями JavaScript, как переменные, типы, функции и области видимости, вы можете прочитать об этих темах в Повторное вступление в JavaScript. Вы также можете обратиться к JavaScript Guide.

- -

Объектно-ориентированное программирование

- -

Объектно-ориентированное программирование (ООП) — это парадигма программирования, которая использует {{glossary("абстракции")}}, чтобы создавать модели, основанные на объектах реального мира. ООП использует несколько техник из ранее признанных парадигм, включая {{glossary("модульность")}}, {{glossary("полиморфизм")}} и {{glossary("инкапсуляция")}}. На сегодняшний день многие популярные языки программирования (такие как Java, JavaScript, C#, C++, Python, PHP, Ruby и Objective-C) поддерживают ООП.

- -

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

- -

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

- -

Терминология

- -
-
{{Glossary("Пространство имён")}}
-
Контейнер, который позволяет разработчикам связать всю функциональность под уникальным, специфичным для приложения именем.
-
{{Glossary("Класс")}}
-
Определяет характеристики объекта. Класс является описанием шаблона свойств и методов объекта.
-
{{Glossary("Объект")}}
-
Экземпляр класса.
-
{{Glossary("Свойство")}}
-
Характеристика объекта, например, цвет.
-
{{Glossary("Метод")}}
-
Возможности объекта, такие как ходьба. Это подпрограммы или функции, связанные с классом.
-
{{Glossary("Конструктор")}}
-
Метод, вызываемый в момент создания экземпляра объекта. Он, как правило, имеет то же имя, что и класс, содержащий его.
-
{{Glossary("Наследование")}}
-
Класс может наследовать характеристики от другого класса.
-
{{Glossary("Инкапсуляция")}}
-
Способ комплектации данных и методов, которые используют данные.
-
{{Glossary("Абстракция")}}
-
Совокупность комплексных наследований, методов и свойств объекта должны адекватно отражать модель реальности.
-
{{Glossary("Полиморфизм")}}
-
Поли означает "много", а морфизм "формы". Различные классы могут объявить один и тот же метод или свойство.
-
- -

Для более обширного описания объектно-ориентированного программирования, см {{interwiki("wikipedia", "Объектно-ориентированное_программирование")}} в Wikipedia.

- -

Прототипное программирование

- -

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

- -

Оригинальный (и наиболее каноничный) пример прототипно-ориентированного языка это {{interwiki("wikipedia", "Self (programming language)", "Self")}} разработанный Дэвидом Ангаром и Ренделлом Смитом. Однако бесклассовый стиль программирования стал набирать популярность позднее, и был принят для таких языков программирования, как JavaScript, Cecil, NewtonScript, Io, MOO, REBOL, Kevo, Squeak (при использовании фреймворка Viewer для манипуляции компонентами Morphic) и некоторых других.1

- -

Объектно-ориентированное программирование в JavaScript

- -

Пространство имён

- -

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

- -
-

Важно отметить, что на уровне языка в JavaScript нет разницы между пространством имён и любым другим объектом. Это отличает JS от множества других объектно-ориентированных языков и может стать причиной путаницы у начинающих JS программистов.

-
- -

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

- -

Давайте создадим глобальный объект MYAPP:

- -
// Глобальное пространство имён
-var MYAPP = MYAPP || {};
- -

Во фрагменте кода выше мы сначала проверяем определён ли объект MYAPP (в текущем файле или другом файле). Если да, то используем существующий глобальный объект MYAPP, иначе создаём пустой объект MYAPP, в котором мы инкапсулируем все методы, функции, переменные и объекты.

- -

Также мы можем создать подпространство имён (учтите, что сначала нужно объявить глобальный объект):

- -
// Подпространство имён
-MYAPP.event = {};
- -

Далее следует пример синтаксиса создания пространства имён и добавления переменных, функций и методов:

- -
// Создаём контейнер MYAPP.commonMethod для общих методов и свойств
-MYAPP.commonMethod = {
-  regExForName: "", // определяет регулярное выражение для валидации имени
-  regExForPhone: "", // определяет регулярное выражение для валидации телефона
-  validateName: function(name){
-    // Сделать что-то с name, вы можете получить доступ к переменной regExForName
-    // используя "this.regExForName"
-  },
-
-  validatePhoneNo: function(phoneNo){
-    // Сделать что-то с номером телефона
-  }
-}
-
-// Объект вместе с объявлением методов
-MYAPP.event = {
-    addListener: function(el, type, fn) {
-    // код
-    },
-    removeListener: function(el, type, fn) {
-    // код
-    },
-    getEvent: function(e) {
-    // код
-    }
-
-    // Можно добавить другие свойства и методы
-}
-
-// Синтаксис использования метода addListener:
-MYAPP.event.addListener("yourel", "type", callback);
- -

Стандартные встроенные объекты

- -

В JavaScript есть несколько объектов, встроенных в ядро, например {{jsxref("Math")}}, {{jsxref("Object")}}, {{jsxref("Array")}} и {{jsxref("String")}}. Пример ниже показывает как использовать объект Math, чтобы получить случайное число, используя его метод random().

- -
console.log(Math.random());
-
- -
Примечание: В данном примере и далее мы будем использовать глобальную функцию {{domxref("console.log()")}}. Если точнее, то функция console.log() не является частью JavaScript, но она поддерживается многими браузерами для облегчения отладки.
- -

Смотрите JavaScript Reference: Standard built-in objects, чтобы ознакомиться со списком всех встроенных объектов JavaScript.

- -

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

- -

Объекты, создаваемые пользователем

- -

Класс

- -

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

- -
var Person = function () {};
-
- -

Объект (экземпляр класса)

- -

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

- -

В примере выше мы определили класс Person. В примере ниже мы создаём два его экземпляра (person1 и person2).

- -
var person1 = new Person();
-var person2 = new Person();
-
- -
Ознакомьтесь с {{jsxref("Object.create()")}}, новым, дополнительным методом инстанцирования, который создаёт неинициализированный экземпляр.
- -

Конструктор

- -

Конструктор вызывается в момент создания экземпляра класса (в тот самый момент, когда создаётся объект). Конструктор является методом класса. В JavaScript функция служит конструктором объекта, поэтому нет необходимости явно определять метод конструктор. Любое действие определённое в конструкторе будет выполнено в момент создания экземпляра класса.

- -

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

- -

В примере ниже, конструктор класса Person выводит в консоль сообщение в момент создания нового экземпляра Person.

- -
var Person = function () {
-  console.log('instance created');
-};
-
-var person1 = new Person();
-var person2 = new Person();
-
- -

Свойство (атрибут объекта)

- -

Свойства — это переменные, содержащиеся в классе; каждый экземпляр объекта имеет эти свойства. Свойства устанавливаются в конструкторе (функции) класса, таким образом они создаются для каждого экземпляра.

- -

Ключевое слово this, которое ссылается на текущий объект, позволяет вам работать со свойствами класса. Доступ (чтение и запись) к свойствам снаружи класса осуществляется синтаксисом InstanceName.Property, так же как в C++, Java и некоторых других языках. (Внутри класса для получения и изменения значений свойств используется синтаксис this.Property)

- -

В примере ниже, мы определяем свойство firstName для класса Person при создании экземпляра:

- -
var Person = function (firstName) {
-  this.firstName = firstName;
-  console.log('Person instantiated');
-};
-
-var person1 = new Person('Alice');
-var person2 = new Person('Bob');
-
-// Выводит свойство firstName в консоль
-console.log('person1 is ' + person1.firstName); // выведет "person1 is Alice"
-console.log('person2 is ' + person2.firstName); // выведет "person2 is Bob"
-
- -

Методы

- -

Методы — это функции (и определяются как функции), но с другой стороны следуют той же логике, что и свойства. Вызов метода похож на доступ к свойству, но вы добавляете () на конце имени метода, возможно, с аргументами. Чтобы объявить метод, присвойте функцию в именованное свойство свойства prototype класса. Потом вы сможете вызвать метод объекта под тем именем, которое вы присвоили функции.

- -

В примере ниже мы определяем и используем метод sayHello() для класса Person.

- -
var Person = function (firstName) {
-  this.firstName = firstName;
-};
-
-Person.prototype.sayHello = function() {
-  console.log("Hello, I'm " + this.firstName);
-};
-
-var person1 = new Person("Alice");
-var person2 = new Person("Bob");
-
-// вызываем метод sayHello() класса Person
-person1.sayHello(); // выведет "Hello, I'm Alice"
-person2.sayHello(); // выведет "Hello, I'm Bob"
-
- -

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

- -
var Person = function (firstName) {
-  this.firstName = firstName;
-};
-
-Person.prototype.sayHello = function() {
-  console.log("Hello, I'm " + this.firstName);
-};
-
-var person1 = new Person("Alice");
-var person2 = new Person("Bob");
-var helloFunction = person1.sayHello;
-
-// выведет "Hello, I'm Alice"
-person1.sayHello();
-
-// выведет "Hello, I'm Bob"
-person2.sayHello();
-
-// выведет "Hello, I'm undefined" (or fails
-// with a TypeError in strict mode)
-helloFunction();
-
-// выведет true
-console.log(helloFunction === person1.sayHello);
-
-// выведет true
-console.log(helloFunction === Person.prototype.sayHello);
-
-// выведет "Hello, I'm Alice"
-helloFunction.call(person1);
- -

Как показывает пример, все ссылки, которые мы имеем на функцию sayHello — person1, Person.prototype, переменная helloFunction и т.д. — ссылаются на одну и ту же функцию. Значение this в момент вызова функции зависит от того, как мы её вызываем. Наиболее часто мы обращаемся к this в выражениях, где мы получаем функцию из свойства объекта — person1.sayHello() — this устанавливается на объект, из которого мы получили функцию (person1), вот почему person1.sayHello() использует имя "Alice", а person2.sayHello() использует имя "Bob". Но если вызов будет совершён иначе, то this будет иным: вызов this из переменной — helloFunction() — установит this на глобальный объект (window в браузерах). Так как этот объект (вероятно) не имеет свойства firstName, функция выведет "Hello, I'm undefined" (так произойдёт в нестрогом режиме; в strict mode всё будет иначе (ошибка), не будем сейчас вдаваться в подробности, чтобы избежать путаницы). Или мы можем указать this явно с помощью Function#call (или Function#apply) как показано в конце примера.

- -
Примечание: Смотрите подробнее о this в  Function#call и Function#apply
- -

Наследование

- -

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

- -
Примечание: JavaScript не обнаружит prototype.constructor класса потомка (смотрите Object.prototype) так что мы должны указать его вручную. Смотрите вопрос "Why is it necessary to set the prototype constructor?" на Stackoverflow.
- -

В примере ниже мы определяем класс Student как потомка класса Person. Потом мы переопределяем метод sayHello() и добавляем метод addGoodBye().

- -
// Определяем конструктор Person
-var Person = function(firstName) {
-  this.firstName = firstName;
-};
-
-// Добавляем пару методов в Person.prototype
-Person.prototype.walk = function(){
-  console.log("I am walking!");
-};
-
-Person.prototype.sayHello = function(){
-  console.log("Hello, I'm " + this.firstName);
-};
-
-// Определяем конструктор Student
-function Student(firstName, subject) {
-  // Вызываем конструктор родителя, убедившись (используя Function#call)
-  // что "this" в момент вызова установлен корректно
-  Person.call(this, firstName);
-
-  // Инициируем свойства класса Student
-  this.subject = subject;
-};
-
-// Создаём объект Student.prototype, который наследуется от Person.prototype.
-// Примечание: Распространённая ошибка здесь, это использование "new Person()", чтобы создать
-// Student.prototype. Это неверно по нескольким причинам, не в последнюю очередь
-// потому, что нам нечего передать в Person в качестве аргумента "firstName"
-// Правильное место для вызова Person показано выше, где мы вызываем
-// его в конструкторе Student.
-Student.prototype = Object.create(Person.prototype); // Смотрите примечание выше
-
-// Устанавливаем свойство "constructor" для ссылки на класс Student
-Student.prototype.constructor = Student;
-
-// Заменяем метод "sayHello"
-Student.prototype.sayHello = function(){
-  console.log("Hello, I'm " + this.firstName + ". I'm studying "
-              + this.subject + ".");
-};
-
-// Добавляем метод "sayGoodBye"
-Student.prototype.sayGoodBye = function(){
-  console.log("Goodbye!");
-};
-
-// Пример использования:
-var student1 = new Student("Janet", "Applied Physics");
-student1.sayHello();   // "Hello, I'm Janet. I'm studying Applied Physics."
-student1.walk();       // "I am walking!"
-student1.sayGoodBye(); // "Goodbye!"
-
-// Проверяем, что instanceof работает корректно
-console.log(student1 instanceof Person);  // true
-console.log(student1 instanceof Student); // true
-
- -

Относительно строки Student.prototype = Object.create(Person.prototype);: В старых движках JavaScript, в которых нет  Object.create можно использовать полифил (ещё известный как "shim") или функцию которая достигает тех же результатов, такую как:

- -
function createObject(proto) {
-    function ctor() { }
-    ctor.prototype = proto;
-    return new ctor();
-}
-
-// Пример использования:
-Student.prototype = createObject(Person.prototype);
-
- -
Примечание: Смотрите Object.create для более подробной информации, и shim для реализации на старых движках.
- -

Инкапсуляция

- -

В примере выше классу Student нет необходимости знать о реализации метода walk() класса Person, но он может его использовать; Класс Student не должен явно определять этот метод, пока мы не хотим его изменить. Это называется инкапсуляция, благодаря чему каждый класс собирает данные и методы в одном блоке.

- -

Сокрытие информации распространённая особенность, часто реализуемая в других языках программирования как приватные и защищённые методы/свойства. Однако в JavaScript можно лишь имитировать нечто подобное, это не является необходимым требованием объектно-ориентированного программирования.2

- -

Абстракция

- -

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

- -

В JavaScript класс Function наследуется от класса Object (это демонстрирует специализацию), а свойство Function.prototype это экземпляр класса Object (это демонстрирует композицию).

- -
var foo = function () {};
-
-// выведет "foo is a Function: true"
-console.log('foo is a Function: ' + (foo instanceof Function));
-
-// выведет "foo.prototype is an Object: true"
-console.log('foo.prototype is an Object: ' + (foo.prototype instanceof Object));
- -

Полиморфизм

- -

Так как все методы и свойства определяются внутри свойства prototype, различные классы могут определять методы с одинаковыми именами; методы находятся в области видимости класса в котором они определены, пока два класса не имеют связи родитель-потомок (например, один наследуется от другого в цепочке наследований).

- -

Примечания

- -

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

- -

Существуют другие способы, которые реализуют ещё более продвинутое объектно-ориентированное программирование на JavaScript, но они выходят за рамки этой вводной статьи.

- -

Ссылки

- -
    -
  1. Wikipedia. "Object-oriented programming"
  2. -
  3. Wikipedia. "Encapsulation (object-oriented programming)"
  4. -
-- cgit v1.2.3-54-g00ecf