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

обратная связь: t.me/dmorenogogoleva
Download Telegram
ахах, забудьте всё, что вы читали до этого, в 2019 объекты наследуются по-другому

- создать: Object.create(proto, [descriptors])
- узнать прототип: Object.getPrototypeOf(obj)
- установить прототип: Object.setPrototypeOf(obj, proto)
const animal = {
say: 'woff'
}

const catOfCats = {
say: 'meow'
}

const cat = Object.create(animal)

Object.getPrototypeOf(cat)
// {say: "woff"}

Object.setPrototypeOf(cat, catOfCats)

cat.say
// "meow"
можно делать так:

const klyaksa = Object.create(animal, {
color: {
value: 'white'
}
});


klyaksa.color
// "white"
классы

синтаксический сахар над функциями-конструкторами, но не совсем (различия тут https://learn.javascript.ru/class#ne-prosto-sintaksicheskiy-sahar)

функция-конструктор
const UserF = function(name) {

this.name = name

this.sayHi = () => `hi! my name is ${this.name}`
}


const Masha = new UserF('Masha')

Masha.sayHi()
// "hi! my name is Masha"

класс
class UserC{
constructor(name) {
this.name = name
}

sayHi() {
return`hi! my name is ${this.name}`
}
}

const Masha = new UserC('Masha')

Masha.sayHi()
// "hi! my name is Masha"
когда мы делаем 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