# OTUS ## Javascript Basic ### Вопросы? ### Контекст при работе с функциями ### Функции - тип данных - object - ссылочный тип данных - `typeof` возвращает `function` Характеристики функции: - Имя функции - Число и тип параметров - Тип возвращаемого значения - Контекст #### Способы создания функции ```js [1-30] // Создание функции 1 // Function declaration // - работает hosting // - всегда есть имя function greet1(name) { console.log("Hello, " + name); } greet1(); ``` ```js [1-30] // Создание функции 2 // Functional Expression // - не работает хоистинг инициализации (хоистинг объявления зависит от типа переменной) // - имя опционально (а если задано - доступно ТОЛЬКО внутри функции) let greet2 = function innerGreetName(name) { console.log("Hello, " + name); }; let greet22 = function (name) { console.log("Hello, " + name); }; greet2(); ``` ```js [1-30] // Создание функции 3 // Function by constructor // - не работает хоистинг инициализации (хоистинг объявления зависит от типа переменной) // - имени нет, или нужно задавать вручную let greet3 = new Function("name", "return 'Hola, ' + name;"); greet3(); ``` **Функции высшего порядка** - функции, которые принимают параметром и/или возвращают функции как результат работы. ```js [1-30] let createGreet = function (age) { let text = age > 18 ? "Приветствую" : "Хаюшки"; return function (name) { console.log(text + ", " + name); }; }; let greet1 = createGreet(45); greet1("Роберт"); // ? let greet2 = createGreet(11); greet2("Саня"); // ? ``` ```js [1-30] document.findElementById("btn").addEventListener("click", function () { alert("*Opa!"); }); ``` Функция - объект ```js [1-30] let greet = function (name) { return "Hi, " + name; }; console.log(typeof greet); // ? console.log(greet.hasOwnProperty("hasOwnProperty")); console.log(greet.hasOwnProperty("toString")); console.log(greet.toString()); ``` Функция может быть свойством объекта ```js [1-30] let o = { method: function (param) { console.log("Do something with", param); }, }; o.method("icecream"); // ? ``` ### Вопросы? #### Замыкания Замыкания в JS - механизм, который позволяет внутри функции получать доступ к переменным, доступным в месте создания функции. ```js [1-30] var createGreet = function (age) { var text = age > 18 ? "Приветствую" : "Хаюшки"; return function (name) { console.log(text + ", " + name); }; }; var greet1 = createGreet(45); greet1("Роберт"); ``` ```js [1-30] function getCounter() { let i = 0; return { next: function () { i = i + 1; }, reset: function () { i = 0; }, current: function () { return i; }, }; } let counter = getCounter(); console.log(counter.current()); // ? counter.next(); counter.next(); console.log(counter.current()); // ? counter.reset(); console.log(counter.current()); // ? ``` Доступ к параметрам функции - по имени - через [`arguments`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/arguments) (не работает в стрелочных функциях) Для работы с неопределенным числом параметров принято использовать [`rest params`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Rest_parameters) ```js [1-30] function sum(...values) { return values.reduce((acc, el) => acc + el); } function myFun(a, b, ...manyMoreArgs) { console.log("a", a); console.log("b", b); console.log("manyMoreArgs", manyMoreArgs); } ``` ### Вопросы? ### Особенности работы с функциями #### Контекст (`this`) Контекст - определяет в рамках какого **объекта** **выполняется функция**. Определяется тем, какое значение имеет ключевое слово [`this`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/this) **при выполнении** функции. Позволяет изменять/задавать поведение функции. [Строгий режим Javascript](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Strict_mode) - использование ограниченной семантики языка для улучшения стабильности, и который упрощает понимание того, что происходит в программе при возникновении проблем. Обычный, нестрогий, режим выполнения JavaScript иногда называется Грязным режимом (Sloppy mode). Три возможных варианта - window - undefined - объект ```js [1-30] // window function someStrangeFunction() { console.log("this for someStrangeFunction", this); } someStrangeFunction(); ``` ```js [1-30] "use strict"; // undefined function someStrangeFunction() { console.log("this for someStrangeFunction", this); } someStrangeFunction(); ``` ```js [1-30] // object var o = { prop1: 1, someStrangeFunctionInObject: function () { console.log("this for someStrangeFunctionInObject", this); }, }; o.someStrangeFunctionInObject(); ``` ```js [1-30] var o = { prop1: 1, someStrangeFunctionInObject: function () { console.log("this for someStrangeFunctionInObject", this); }, }; let func = o.someStrangeFunctionInObject; func(); //? ``` ```js [1-30] function someStrangeFunction() { console.log("this for someStrangeFunction", this); } let o = { prop1: 1 }; someStrangeFunction(); // ? o.someStrangeMethod = someStrangeFunction; o.someStrangeMethod(); // ? ``` ```js [1-30] // Об этом важно помнить при передаче методов let o = { name: "Bob", greet: function () { console.log("Hello, " + this.name); }, }; document.body.addEventListener("click", o.greet); ``` ```js [1-30] let o = { name: "Bob", greet: function () { console.log("Hello, " + this.name); }, }; let x = o.greet; x(); // ? ``` #### Изменение и фиксирование контекста ```js [1-30] let o = { prop1: 1, name: "Sam" }; let f = function () { console.log(this); }; f(); // ? ``` ```js [1-30] let o = { prop1: 1, name: "Sam" }; let f = function (x) { console.log(this, x); }; o.of = f; o.of(1); // o, 1 f.call(o, 2); // o, 2 f.apply(o, [3]); // o, 3 var of = f.bind(o); of(4); // o, 4 ``` ```js [1-30] let o = { prop1: 1, name: "Sam" }; let f = function (name) { console.log(this, name); }; f.call(o, "user 2"); // параметры один за одним f.apply(o, ["user 3"]); // параметры списком f.bind(o)("user 4"); // bind возвращает функцию для вызова ``` ### Вопросы? [Практика](https://codesandbox.io/s/github/vvscode/otus--javascript-basic/tree/master/lessons/lesson03/code/bind) Напишите функцию, которая позволит привязывать контекст, так, как это делает метод `.bind` (сам метод использовать нельзя). ### Вопросы? ### [Стрелочные функции](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions) - короткий синтаксис - только Functional expression - нет имени - привязаны к значению `this`, который определяется в момент определения функции (кроме class properties) - не могут быть конструкторами - в них не работают `arguments` / `new.target` / `super` / `yeild` - удобны для inline использования ```js [1-30] // блочная форма let double1 = (a) => { return a * 2; }; // Когда один аргумент - скобки можно опускать // prettier-ignore let double2 = a => { return a * 2; }; // При коротком возвращении - блок и return можно опускать // prettier-ignore let double3 = a => a * 2; // а иногда (НО не пишите так никогда) // prettier-ignore let func = _ => new Date().toLocaleTimeString(); ``` ```js [1-30] // НО! let func1 = () => { foo: 1; }; func(); // undefined let func2 = () => ({ foo: 1 }); func2(); // { foo: 1 } ``` [Про label](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/label) ```js [1-30] let o = { name: "Bob", greet: () => { console.log("Hello, " + this.name); }, }; document.body.addEventListener("click", o.greet); //? ``` ```js [1-30] function O() { this.name = "Bob"; this.greet = () => { console.log("Hello, " + this.name); }; } document.body.addEventListener("click", new O().greet); //? ``` ```js [1-30] let O = function () { this.name = "Bob"; this.greet = () => { console.log("Hello, " + this.name); }; }; let greet = new O().greet; greet.call({ name: "Sam" }); // ? ``` ### Вопросы? ### Что со всем этим делать? _Понять, простить и пользоваться_ - [Использовать чужие методы на своих объектах](https://learn.javascript.ru/native-prototypes#zaimstvovanie-u-prototipov) ### Дополнительные материалы - [Продвинутая работа с функциями](https://learn.javascript.ru/advanced-functions) ### Вопросы? #### Вопросы для самопроверки Как проверить, что вы усваиваете материал в срок (не все из этого давалось на занятиях) 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. Что такое делегирование событий? Преимущества и особенности работы с делегированием?