code_notes
71 subscribers
136 photos
1 video
134 links
учусь делать веб

обратная связь: t.me/dmorenogogoleva
Download Telegram
когда мы делаем class Cat extends Animal мы добавляем ссылку на [[Prototype]] из Cat.prototype в Animal.prototype

в реальной жизни мы используем это когда class User extends React.Component и получаем в нашем компоненте componentDidMount и проч. методы
через super можно вызвать родительский метод

class Animal {
constructor(name) {
this.name = name
}

say() {
console.log('animal ooo')
}
}

class Cat extends Animal {
say() {
super.say()
return 'meow'
}
}

const cat = new Cat('Клякса')

cat.say()
// animal ooo
// "meow"
если мы хотим добавить что-то в конструктор, нужно обязательно писать ключевое слово super(), пушто до вызова super() у нас нет this

class Cat extends Animal {

constructor(name, color) {
super(name);
this.color = color;
}
}
статические методы

при объявлении помечаются словом static

присваиваются не классу, а его prototype

class User {
static staticMethod() {
...
}
}

то же самое что
User.staticMethod = function() {
...
};
обычно статические методы используются для реализации функций, принадлежащих классу, но не к каким-то конкретным его объектам.

обычно вызываются из класса

class Article {
constructor(title, date) {
this.title = title;
this.date = date;
}

static createTodays() {
return new this("Сегодняшний дайджест", new Date());
}
}

let article = Article.createTodays();
из экземпляра класса этот метод вызвать нельзя
пример из реальной жизни

метод getInitialProps, который предоставляется фреймворком next
он выполняется на сервере и может снабдить нас полезнейшей информацией типа текущего урла

статейка о том, как можно побыстрее фетчить данные с помощью этого метода
https://nextjs.org/learn/basics/fetching-data-for-pages
приватные методы и свойства

для того, чтобы юзать свойство снаружи удобнее всего использовать get как геттер и функцию как сеттер
Чтобы поймать unhandledrejection нужно навесить обработчик на window

window.addEventListener('unhandledrejection', function(event) {
// объект события имеет два специальных свойства:
alert(event.promise); // [object Promise] - промис, который сгенерировал ошибку
alert(event.reason); // Error: Ошибка! - объект ошибки, которая не была обработана
});
статические методы промисов

1. Promise.all — принимает массив промисов (может принимать любой перебираемый объект, но обычно используется массив) и возвращает новый промис. Новый промис завершится, когда завершится весь переданный список промисов, и его результатом будет массив их результатов

Если любой из промисов завершится с ошибкой, то промис, возвращённый Promise.all, немедленно завершается с этой ошибкой.

2. Promise.allSettled !нужен полифил!
работает так же как Promise.all, но если один из промисов падает с ошибкой, то он не завершается с ошибкой, а просто передает в массив ответов ошибку вместо результата

3. Promise.race — очень похож на Promise.all, но ждёт только первый промис, из которого берёт результат (или ошибку).

4. Promise.resolve(value) — создаёт успешно выполненный промис с результатом value
let promise = new Promise(resolve => resolve(value));


5. Promise.reject — создаёт промис, завершённый с ошибкой error

let promise = new Promise((resolve, reject) => reject(error));

На практике этот метод почти никогда не используется.
// await будет ждать массив с результатами выполнения всех промисов
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);
Генераторы могут генерировать бесконечно

Почему-то я была уверена, что знаю джаваскрипт. Если не глубоко, то хотя бы знаю про все сущности и их синтаксис. И тут я дочитала до главы про генераторы и ору.

Мне казалось, что генераторы это просто функции-фабрики и я их имплементировала уже пятьсот раз.
Но я ошибалась.

самый простой генератор выглядит так:
function* generateSequence() {
yield 1;
yield 2;
return 3;
}

🤨🤨🤨

а вот его использование:
let generator = generateSequence();

generator.next()
// {value: 1, done: false}

generator.next()
// {value: 2, done: false}

generator.next()
// {value: 3, done: true}

😐😐😐

первая ценность генераторов в том, что они являются перебираемыми объектами
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}

let generator = generateSequence();

for (let value of generator) {
console.log(value)
}
// 1, 2, 3

из генератора можно сделать массив вот так:
[...generateSequence()]

// [1, 2, 3]

вторая ценность генераторов состоит в том, что их можно вкладывать друг в друга
это называется «композиция генераторов»
function* generateSequence(start, end) {
for (let i = start; i <= end; i++) yield i;
}

function* generatePasswordCodes() {

yield* generateSequence(48, 57);

yield* generateSequence(65, 90);

yield* generateSequence(97, 122);

}

let str = '';

for(let code of generatePasswordCodes()) {
str += String.fromCharCode(code);
}

// "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

третья ценность генераторов — способность обмениваться данными с вызывающим кодом
🤯🤯🤯

Чтобы это сделать, нам нужно вызвать generator.next(arg) с аргументом. Этот аргумент становится результатом yield.
function* gen() {
let ask1 = yield "2 + 2 = ?";

console.log(ask1); // 4

let ask2 = yield "3 * 3 = ?"

console.log(ask2); // 9
}

const generator = gen();

console.log(generator.next().value);

console.log(generator.next(4).value);

console.log(generator.next(9).done);
цитата из учебника:
1. Первый .next() начинает выполнение… Оно доходит до первого yield.

2. Результат возвращается во внешний код.

3. Второй .next(4) передаёт 4 обратно в генератор как результат первого yield и возобновляет выполнение.

4. …Оно доходит до второго yield, который станет результатом .next(4).

5. Третий next(9) передаёт 9 в генератор как результат второго yield и возобновляет выполнение, которое завершается окончанием функции, так что done: true.

Получается такой «пинг-понг»: каждый next(value) передаёт в генератор значение, которое становится результатом текущего yield, возобновляет выполнение и получает выражение из следующего yield.
картинка
как используются генераторы в реальной жизни?

судя по всему, очень редко
но можно например сделать набор псевдослучайных чисел для каких-нибудь тестов

function* pseudoRandom(seed) {
let previous = seed;

while(true) {
previous = previous * 16807 % 2147483647
yield previous;
}

};

let generator = pseudoRandom(1);

generator.next().value;
// 16807

generator.next().value;
// 282475249

generator.next().value;
// 1622650073

подробности можно почитать здесь: https://learn.javascript.ru/generators
также в реальной жизни часто используются асинхронные генераторы для постраничного фетчинга данных (считается, что это очень удобно)

скоро я узнаю это точно, потому что в новом проекте у нас мобикс, а с ним принято использовать все генераторные радости
<script type="module">

1. всегда включена директива use strict
2. отложенное (deferred) выполнение по умолчанию
3. атрибут async работает во встроенных скриптах
4. для загрузки внешних модулей с другого источника, он должен ставить заголовки CORS
5. дублирующиеся внешние скрипты игнорируются
6. у модулей есть своя область видимости, обмениваться функциональностью можно через import/export
В реальной жизни модули в браузерах редко используются в «сыром» виде. Обычно, мы объединяем модули вместе, используя специальный инструмент, например Webpack и после выкладываем код на рабочий сервер.

Одно из преимуществ использования сборщика – он предоставляет больший контроль над тем, как модули ищутся, позволяет использовать «голые» модули и многое другое «своё», например CSS/HTML-модули.

Сборщик делает следующее:

Берёт «основной» модуль, который мы собираемся поместить в <script type="module"> в HTML.
Анализирует зависимости (импорты, импорты импортов и так далее)
Собирает один файл со всеми модулями (или несколько файлов, это можно настроить), перезаписывает встроенный import функцией импорта от сборщика, чтобы всё работало. «Специальные» типы модулей, такие как HTML/CSS тоже поддерживаются.
В процессе могут происходить и другие трансформации и оптимизации кода:
Недоступный код удаляется.
Неиспользуемые экспорты удаляются («tree-shaking»).
Специфические операторы для разработки, такие как console и debugger, удаляются.
Современный синтаксис JavaScript также может быть трансформирован в предыдущий стандарт, с похожей функциональностью, например, с помощью Babel.
Полученный файл можно минимизировать (удалить пробелы, заменить названия переменных на более короткие и т.д.).

Если мы используем инструменты сборки, то они объединяют модули вместе в один или несколько файлов, и заменяют import/export на свои вызовы. Поэтому итоговую сборку можно подключать и без атрибута type="module", как обычный скрипт:
<script src="bundle.js"></script>
proxy

обёртка вокруг объекта, которая «по умолчанию» перенаправляет операции над ней на объект, но имеет возможность перехватывать их.

const numbers = [0, 1, 2];


const numbersProxy = new Proxy(numbers, {
get(target, prop) {
if (prop in target) {
return target[prop];
} else {
return 0;
}
}
});

numbers[1]
// 1

numbers[123]
// 0