JS Objects & Classes Flashcards
Визначення класів
Класи в JavaScript були введені в ECMAScript 2015. Це собою синтаксичний цукор над механізмом прототипного успадкування. Синтаксис класів не вводить нову об’єктно-орієнтовану модель, а простіший спосіб створення об’єктів і організації успадкування.
Можна визначати класи за допомогою: class declarations і class expressions.
Перший спосіб визначення класу - class declaration (оголошення класу). Для цього необхідно скористатися ключовим словом class і вказати ім’я класу.
class Rectangle { constructor (height, width) { this.height = height; this.width = width; } }
Різниця між оголошенням функції (function declaration) і оголошенням класу (class declaration) в тому, що оголошення функції здійснює підйом (hoisting), в той час як оголошення класу - ні. Тому спочатку необхідно оголосити клас і тільки потім працювати з ним.
Другий спосіб визначення класу - class expression. Можна створювати іменовані і безіменні вираження. У першому випадку ім’я вираження класу знаходиться в локальній області видимості класу і може бути отримано через властивості самого класу, а не його екземпляра.
// безіменний var Rectangle = class { constructor (height, width) { this.height = height; this.width = width; } };
// іменований const MyClass = class Me { getClassName() { return Me.name; } }; let inst = new MyClass(); console.log(inst.getClassName());
Тіла класів виконуються в строгому режимі (strict mode).
Метод constructor і ключове слово super
constructor() необхідний для ініціалізації об’єктів, створених, за допомогою класу. Може бути тільки один у класі, інакше отримаємо виняток типу SyntaxError.
constructor() визначає функцію, яка представляє собою клас: Foo === Foo.prototype.constructor > true typeof Foo > 'function'
Ключове слово super використовується в методі constructor для виклику конструктора батьківського класу. Також використовується для виклику функцій батьківського класу.
Статичні і прототипні методи класу
Ключове слово static, визначає статичний метод для класу. Статичні методи не можуть бути викликані в екземплярах (instance) класу.
Прототипні методи наслідуються екземплярами класу.
JavaScript Object Property Descriptors
Метод Object.defineProperty дозволяє оголосити властивість і налаштувати її дескриптор.
Метод приймає три параметри Object.defineProperty(obj, “property”, {descriptor}).
obj – об’єкт, в якому оголошується чи змінюється властивість;
“property” – назва властивості;
{descriptor} – об’єкт, який описує поведінку властивості при виконанні певних операцій над нею, як зчитування або запис.
Є дескриптор даних і дескриптор доступу (data descriptor і access descriptor).
Дескриптор даних дає можливість налаштовувати такі атрибути властивості як:
value – значення властивості (за замовчуванням default);
writable – визначає, чи можна змінювати значення напряму через object.property;
configurable – визначає, чи можна видаляти або модифікувати за допомогою Object.defineProperty();
enumerable – визначає чи буде властивість перелічуваною. Кожен об’єкт можна перебрати за допомогою циклу for .. in або ж отримати назви всіх властивостей за допомогою функції Object.keys. enumerable визначає, чи буде властивість перелічуватися в даних ситуаціях.
const fox = {}; Object.defineProperties(fox, { 'name': { value: 'Oliver', enumerable: false }, 'type': { value: 'fox', enumerable: true } });
for (let key in fox) {
console.log(${key}: ${fox[key]}
); // type: fox
}
Object.keys(fox).forEach(key => {
console.log(${key}: ${fox[key]}
); // type: fox
});
(writable, configurable, enumerable за замовчуванням false)
const human = {}; Object.defineProperty( human, “age”, { value: 10, writable: false, configurable: true, enumerable: false } )
console. log(human.age); // 10
human. age = 90;
console. log(human.age); // 10
Дескриптор доступу описується парою функцій – гетером і сетером. Такий дескриптор може містити get(), set(), configurable, enumerable.
Недоліом методу defineProperty() є його повторні виклики для кожного визначення властивості.
Для визначення декількох властивостей за один виклик використовуєтсья метод defineProperties().
const jar = {};
Object.defineProperties(jar, { "numberOfCookies": { value: 0, configurable: true }, "cookies": { get(){ return this.numberOfCookies; }, set(value){ if (value >= 0 && value <= 5) { Object.defineProperty(this, "numberOfCookies", { value: value }); } else { console.error('Количество печенек должно быть от 0 до 5'); } }, enumerable: true } });
console. log(jar.cookies); // 0
jar. numberOfCookies = 4;
console. log(jar.cookies); // 0
jar. cookies = 4;
console. log(jar.cookies); // 4
JavaScript Object Accessors
Object Accessors це функції getter і setter. Їх синтаксис нагадує методи об’єктів, але на початку вказуємо ключові слова get чи set.
set пов’язує властивість об’єкта з функцією, яка буде викликана при спробі встановити нове значення цієї властивість.
get пов’язує властивість об’єкта з функцією, яка буде викликатися при зверненні до цієї властивості.
getter повертає значення властивості, а setter приймає нове значення і встановлює його властивості.
const jar = { numberOfCookies: 0, get cookies() { return this.numberOfCookies; }, set cookies(value) { this.numberOfCookies = value; } };
Щоб отримати значення numberOfCookies => jar.cookies. Виглядає ніби звертаємося до властивості cookies, але насправді ми викликаємо функцію get за іменем cookies.
Jar.cookies = 5 – викликаємо функцію set за іменем cookies.
Така конструкція дає можливість проводити валідацію значення, яке встановлюється.
set cookies(value) { If ( value >=0 ) { this.numberOfCookies = value; } else { console.error(“Error”) } }
Але проблема в тому, що нічого не заважає встановити значення властивості напряму через jar.numberOfCookies = 599.
Для вирішення цієї проблеми використовують метод Object.defineProperty.
OOP Principles
Абстракция - когда переводим объект реального мира в программный объект, то выделяем только те характеристики, которые нужны для выполнения конкретной задачи.
Абстрагирование – это способ выделить набор значимых характеристик объекта, исключая из рассмотрения незначимые. Соответственно, абстракция – это набор всех таких характеристик.
Инкапсуляция - класс может иметь приватные свойства и методы, реализация которых скрыта от внешнего мира, и к которым объекты не имеют прямого доступа, а могут вызывать только публичные методы класса. Таким образом класс как бы скрывает часть своего функционала от пользователя.
Инкапсуляция – это свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе и скрыть детали
реализации от пользователя.
Наследование - дочерний класс унаследует от родительского класс все методы и свойства.
Наследование – это свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым или родительским. Новый класс – потомком, наследником или производным классом.
Полиморфизм - возможность разной реализации методов одного интерфейса.
Например есть несколько классов, которые унаследуют от одного класса, и они имеют разные реализации определенного метода родительского класса.
Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
Наследование, композиция, агрегация - виды отношения объектов
Наследование — это когда класс-наследник имеет все поля и методы родительского класса, и, как правило, добавляет какой-то новый функционал или/и поля.
Ассоциация – это когда один класс включает в себя другой класс в качестве одного из полей. Ассоциация описывается словом «имеет». Автомобиль имеет двигатель. Вполне естественно, что он не будет являться наследником двигателя.
Выделяют два частных случая ассоциации: композицию и агрегацию.
Композиция - включаемый класс может существовать только как часть контейнера (другого класса). Если контейнер будет уничтожен, то и включённый класс тоже будет уничтожен. Экземпляр включенного класса будет создаваться в конструкторе контейнера.
Агрегация – это когда экземпляр включенного класса передается в конструктор контейнера в качестве параметра и может существовать отдельно от контейнера.
Объект
Объект - модель реальной сущности, имеющая конкретные свойства и методы. Объект - екземпляр класса.
ООП и JS
JavaScript — это объектно-ориентированный язык, основанный на прототипировании, а не на классах.
Основанные на классах объектно-ориентированные языки строятся на концепции двух отдельных сущностей: класс и экземпляр.
Класс определяет все свойства, которые характеризуют группу объектов. Класс это абстрактная вещь, а не какой-либо конкретный член множества объектов.
Экземпляр, это воплощение класса в виде конкретного объекта.
JavaScript имеет только объекты. Но имеет понятие прототипа объекта — это объект, используемый в качестве шаблона, с целью задать изначальные свойства для нового объекта.
Любой объект может иметь собственные свойства, присвоенные либо во время создания, либо во время выполнения. Любой объект может быть указан в качестве прототипа для другого объекта.
В классо-ориентированных языках, вы можете определить класс и метод конструктор, чтобы задать начальные значения для свойств экземпляра. Для создания экземпляра класса используется оператор new, совместно с методом конструктора.
В JavaScript определяется функция-конструктор для создания объектов с начальным набором свойств и значений. Любая функция в JavaScript может быть использована, как конструктор. Используется оператор new для создания нового объекта.
В языках, основанных на классах, иерархию классов создается через объявление классов. В объявлении класса вы можете указать, что новый класс является подклассом уже существующего класса.
JavaScript реализует наследование присвоением экземпляра объекта в качестве значения свойства prototype функции-конструктора.
Присваиваем новый экземпляр Employee, в качестве prototype для функции-конструктора Manager. Теперь, когда вы создадите нового Manager, он унаследует свойства из объекта Employee.
function Employee() { this.name = ''; this.dept = 'general'; }
function WorkerBee() { this.projects = []; }
WorkerBee.prototype = new Employee(); var mark = new WorkerBee();
Когда JavaScript видит оператор new, он создает новый объект и неявно устанавливает значение внутреннего свойства [[Prototype]] в WorkerkBee.prototype, затем передает этот новый объект в качестве значения this в функцию-конструктор WorkerBee. Внутреннее свойство [[Prototype]] определяет цепочку прототипов, используемых для получения значений свойств.
Когда вы запрашиваете значение свойства, JavaScript сначала проверяет, существует ли это значение в данном объекте. Если так и есть, тогда возвращается это значение. Если значение не найдено в самом объекте, JavaScript проверяет цепочку прототипов (используя внутреннее свойство [[Prorotype]]).
Поиск свойств в JavaScript начинается с просмотра самого объекта, и если в нем свойство не найдено, поиск переключается на объект, на который указывает ссылка __proto__.
Специальное свойство __proto__ устанавливается автоматически при создании объекта. Оно принимает значение свойства prototype функции-конструктора.
mark.__proto__ == WorkerBee.prototype //true
Все объекты (за исключением глобального объекта Object) имеют свойство __proto__. Все функции имеют свойство prototype.
Оператор instanceof - способ проверки, наследуется ли объект от конкретного конструктора.
Метод Object.create()
Метод Object.create() создаёт новый объект с указанными объектом прототипа и свойствами.
Float
Определяет, по какой стороне будет выравниваться элемент, при этом остальные элементы будут обтекать его с других сторон. Когда значение свойства float равно none, элемент выводится на странице как обычно, при этом допускается, что одна строка обтекающего текста может быть на той же линии, что и сам элемент.
Eсть ли разница между window и document?
Да. У JavaScript есть глобальный объект и всё происходит через него. window – тот самый объект, который хранит глобальные переменные, функции, местоположение, историю. Всё находится внутри него, setTimeout, XMLHttpRequest, console и localStorage также являются частью window. Аналогично дело обстоит и с document, который является свойством объекта window и представляет DOM. Все ноды – это часть document, следовательно, вы можете использовать getElementById или addEventListener для document. Но обратите внимание, что этих методов нет в объекте window.
RxJS
Библиотека для работы с асинхронными данными в виде потока, например клики мыши, или скрол. В центре находится объект Observable и набор операторов для работы с ним.