# OTUS ## Javascript Basic ### Вопросы? ### Прототипное наследование и функции-конструкторы ### Создание объектов ```js [1-30] const user = { name: "Bob", }; ``` Достаточно часто, нам нужно создавать много однотипных объектов ```js [1-30] function getUser(name) { return { name: name, }; } const user1 = getUser("Bob"); const user2 = getUser("Sam"); ``` И часто объекты сопровождаются не просто свойствами, а свойствами-методами (функциями) ```js [1-30] function getUser(name) { return { name, greet: function () { alert(`Hello from ${this.name}`); }, }; } const user1 = getUser("Bob"); const user2 = getUser("Sam"); user1.greet(); ``` в чем проблема такого кода? Используем прототипы для экономии памяти ```js [1-30] const userPrototype = { greet() { alert(`Hello from ${this.name}`); }, }; function getUserWithPrototype(name) { return { name, __proto__: userPrototype, }; } const user1 = getUserWithPrototype("Bob"); const user2 = getUserWithPrototype("Sam"); user1.greet(); ``` ```js [1-30] const userPrototype = { greet() { alert(`Hello from ${this.name}`); }, }; function getUserWithPrototype(name) { return Object.create(userPrototype, { name: { value: name, }, }); } const user1 = getUserWithPrototype("Bob"); const user2 = getUserWithPrototype("Sam"); user1.greet(); ``` ### Вопросы? #### Работа с конструкторами Для упрощения создания объектов в языке предусмотрен механизм вызова функции в качестве конструкторов. Это, к слову, еще один способ изменить `this` (в дополнение к тем, что мы уже рассмотрели) - использовать ключевое слово `new` Алгоритм работы конструктора: - `new` с любой функцией (кроме стрелочной) создает новый объект - созданный объект получает значение `__proto__` (из свойства конструктора `prototype`) - созданный объект ассоциируется с `this` - выполняется функция - если функция возвращает примитивное значение - неявно возвращается `this` ```js [1-30] var f = function (name) { console.log(this); }; f("Sam"); // ? console.log(new f("Bob")); // ? ``` ```js [1-30] function User(name, greet) { // изменяем новый объект при создании this.name = name; this.greetPhrase = greet; this.greet = function () { console.log(this.greetPhrase + ", " + this.name); }; } let u1 = new User("Bob", "Hello"); let u2 = new User("Sam", "hi"); console.log(u1, u2); u1.greet(); u2.greet(); ``` ```js [1-30] function User(name, greet) { this.name = name; this.greetPhrase = greet; } User.prototype = { greet: function () { console.log(this.greetPhrase + ", " + this.name); }, }; let u1 = new User("Bob", "Hello"); let u2 = new User("Sam", "hi"); console.log(u1, u2); u1.greet(); u2.greet(); ``` ```js [1-30] function User(name, greet) { this.name = name; // читаем greet через замыкание this.greet = function () { console.log(greet + ", " + this.name); }; } let u1 = new User("Bob", "Hello"); u1.greet(); document.body.addEventListener("click", u1.greet); ``` ```js [1-30] function User(name, greet) { this.name = name; // Фиксируем контекст this.greet = () => { console.log(greet + ", " + this.name); }; } let u2 = new User("Bob", "Hello"); u2.greet(); document.body.addEventListener("click", u2.greet); ``` Нужно отметить, что задание прототипа, это [не единственное, что делают конструкторы](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes/constructor) Функции-конструкторы - вариант создания "классов" до-ES6 мира. В целом, современные классы являются "синтаксическим сахаром" и так же работают на прототипах, просто позволяют нам использовать другой синтаксис для описания. ```js [1-30] // ES5 function User(name, greet) { this.name = name; this.greetPhrase = greet; } User.prototype = { greet: function () { console.log(this.greetPhrase + ", " + this.name); }, }; ``` ```js [1-30] // ES6 class User { constructor(name, greet) { this.name = name; this.greetPhrase = greet; } greet() { console.log(this.greetPhrase + ", " + this.name); } } console.log(User.prototype); let u3 = new User("Bob", "Hello"); u3.greet(); document.body.addEventListener("click", u3.greet); ``` ```js [1-30] // ES6 class User { constructor(name, greet) { this.name = name; this.greetPhrase = greet; } // https://babeljs.io/docs/en/babel-plugin-proposal-class-properties greet = () => { console.log(this.greetPhrase + ", " + this.name); }; } console.log(User.prototype); let u4 = new User("Bob", "Hello"); u4.greet(); document.body.addEventListener("click", u4.greet); ``` ### Вопросы? #### Как проверить, что объект является экземпляром класса? ```js [1-30] function User() {} var fu = {}; var u = new User(); console.log(fu, fu instanceof User); console.log(u, u instanceof User); ``` `instanceof` ходит по цепочке прототипов и ищет совпадение с `prototype` ``` x instanceof Y -> x.__proto__ === Y.prototype -> x.__proto__.__proto__ === Y.prototype -> ... ``` ```js [1-30] let o = {}; console.log(o instanceof Array); // ? o.__proto__ = []; // o.__proto__.__proto__ === Array.prototype console.log(o instanceof Array); ``` ### Вопросы? [Практика](https://codesandbox.io/s/github/vvscode/otus--javascript-basic/tree/master/lessons/lesson03/code/singleton) Напишите функцию или класс, которые будут являться синглтоном. Напишите функцию, которая делает синглтоны на основе других классов. ### Вопросы? ### Что со всем этим делать? _Понять, простить и пользоваться_ - Читать документацию, например [методы функций](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function) / [другие встроенные объекты](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects) - [Monkey patching](https://learn.javascript.ru/native-prototypes#native-prototype-change) ### [Домашнее задание](https://github.com/vvscode/otus--javascript-basic/blob/master/lessons/lesson03/homework_lec3.md) #### Вопросы для самопроверки Как проверить, что вы усваиваете материал в срок (не все из этого давалось на занятиях) 1. Что такое контекст вызова функции? Чем определяется? 2. Как изменить this внутри функции? (5 способов) 3. чем различаются .call / .apply / .bind 4. Что такое сигнатура функции? 5. Чем характеризуется функция? 6. Что такое прототип? 7. Как работает конструктор? Что происходит при вызове со словом new ? 8. Как происходит чтение свойств из объекта? 9. Как происходит запись свойств в объект? 10. Как проверить на принадлежность классу? 11. Как работает instanceof ? 12. Четыре принципа ООП 13. Виды полиморфизма. И их объяснение 14. Событийный цикл в javascript 15. Что такое фаза захвата / capturing ? 16. Что такое фаза всплытия / bubbling ? 17. Как подписаться на событие документа / html элемента? 18. Что такое Функция высшего порядка? 19. Что такое синхронный / асинхронный код? 20. Что такое каррирование ? 21. Что такое паттерн цепочка ? Как реализовать? 22. В чем разница объявления методов в конструкторе и на .prototype ? 23. Что такое 'полифилл'? 24. Что такое "стрелочная" ("arrow function") функция? Чем она отличается от обычной? 25. Что такое CORS? 26. Что такое и какие есть коды ответов HTTP? 27. Что такое делегирование событий? Преимущества и особенности работы с делегированием?