Простий JavaScript — все про js, ts, node.js, react
1 subscriber
19 photos
31 links
Learn to Code, One Byte at a Time

Зрозумілою мовою про JavaScript, React, Node.js (Express), TypeScript

Мета каналу — краще зрозуміти основи програмування та допомогти іншим. Для тих, хто тільки починає вивчати програмування та хоче зрозуміти основи
Download Telegram
Існує 6 основних методів пошуку елементів у DOM:

elem.querySelector(css) — повертає перший елемент, що відповідає даному CSS-селектору.
elem.querySelectorAll(css) повертає всі елементи всередині elem, що відповідають заданому CSS-селектору. ('ul > li:last-child') або ("#list li:not(#disabled)")
document.getElementById(id) ,наприклад, ('elem'); Метод getElementById можна викликати лише для об’єкта document. Він шукає вказаний id у всьому документі.

getElementsByName
getElementsByTagName
getElementsByClassName

getElementsByName('username') поверне всі елементи з атрибутом name="username", getElementsByTagName('div') поверне всі елементи div, а getElementsByClassName('my-class') поверне всі елементи з класом my-class.

#jsquestions
Cписок найпоширеніших DOM-подій:

Події миші:

click – відбувається, коли клацнули на елемент лівою кнопкою миші (на пристроях із сенсорними екранами воно відбувається при торканні).
contextmenu – відбувається, коли клацнули на елемент правою кнопкою миші.
mouseover / mouseout – коли миша наводиться на / залишає елемент.
mousedown / mouseup – коли натиснули / відпустили кнопку миші на елементі.
mousemove – під час руху миші.

Події клавіатури:
keydown та keyup – коли користувач натискає / відпускає клавішу.

Події елементів форми:
submit – користувач надіслав форму <form>.
focus – користувач фокусується на елементі, наприклад, натискає на <input>.

Події документа:
DOMContentLoaded – коли HTML завантажено й оброблено, DOM документа повністю побудований і доступний.

CSS події:
transitionend – коли CSS-анімацію завершено.

#jsquestions
Обробники подій
Використання атрибута HTML
HTML
<input type="button" onclick="alert('Клік!')" value="Кнопка">

HTML + JS:
<input type="button" id="button" value="Кнопка">
<script>
button.onclick = function() {
alert('Клік!');
};
</script>

Доступ до елемента через this
<button onclick="alert(this.innerHTML)">Натисни на мене</button>


addEventListener
Фундаментальний недолік описаних вище способів присвоєння обробника – неможливість повісити кілька обробників для однієї події.
element.addEventListener(event, handler, [options]);

event Назва події, наприклад "click". handler Посилання на функцію-обробник. options Додатковий об’єкт із властивостями
function handler() {
alert( 'Дякую!' );
}

input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);


#jsquestions
https://jschallenger.com/ — рекомендую сайт для вивчення базису по js чи повторення.

Складається з трех частин Javascript Basics, Javascript DOM та Javascript Practice.

Спочатку теорія, потім практика. У розділі Javascript DOM — чомусь я не знайшов теорії - одразу практика, тому розбираюсь сам з гуглом.

Можна тестово пройти пару занять, але доступ до всього контенту коштує 10$ за місяць, як похід в мак. Але пройти можна за 2-5 днів, тому це того вартує, дуже хороший базис по js.

Потім я би рекомендував https://www.freecodecamp.org/ - Basic/Intermediate Algorithm Scripting
Простий JavaScript — все про js, ts, node.js, react
Модифікатори доступу визначають рівень доступу до властивостей та методів класу. TypeScript надає три типи модифікаторів доступу: public, private і protected. - public дозволяє доступ до властивостей та методів з будь-якого місця, - private обмежує доступ…
якщо б tenets були з модифікатором доступу публічними — то будь хто міг би додати через house.tenets.push() когось з сусідів. Але коли там private — це всім показує, що він є приватним і додавати можна тільки через функцію, якщо це передбачено (наприклад, рядки 23-24). Також, це покращує безпеку коду, оскільки воно дозволяє контролювати доступ до даних та запобігати їх несанкціонованій зміні із зовнішнього коду.


#tsquestions
Конструктор у класі схожий на функцію з параметрами у круглих дужках, але записується без круглих дужок та використовує ключове слово constructor. Конструктор є спеціальним методом класу, який викликається під час створення екземпляра класу. У ньому визначаються властивості та методи екземпляра класу, а також може виконуватись ініціалізація початкових значень.

Наприклад, у класі Person нижче конструктор визначає властивості name і age та надає їм початкові значення, передані як параметри конструктора:

class Person {
name: string;
age: number;

constructor(name: string, age: number) {
this.name = name;
this.age = age;
}

greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}

const person = new Person('John', 30);
person.greet(); // Output: "Hello, my name is John and I'm 30 years old."


Коли створюємо екземпляр класу Person через new Person('John', 30), викликається конструктор Person і створюється новий об'єкт із заданими властивостями name і age.

Тобто в класі конструктор - місце для початкових змінних(властивостей) екземпляра класу, щоб їх ініціалізувати, а потім ними можна вже оперувати, створювати функції тд.

Крім ініціалізації властивостей екземпляра класу, конструктор може виконувати інші дії, такі як перевірка параметрів конструктора або виклик інших методів класу для додаткового налаштування об'єкта. Конструктор може бути використаний для створення та ініціалізації інших об'єктів, які будуть використовуватися в методах класу.

#jsquestions
Intersection Types (перетин типів) у TypeScript - це можливість створювати нові типи, які об'єднують два або більше існуючих типів. Синтаксис перетину типів використовує оператор "&". Результуючий тип містить всі властивості та методи, які є в кожному з типів, що перетинаються.

type Person = {
name: string;
age: number;
}

type Employee = {
id: number;
position: string;
}
type PersonWithEmployee = Person & Employee;

const person: PersonWithEmployee = {
name: "John",
age: 30,
id: 123,
position: "Developer",
};

#tsquestions
Type Guards (захист типів) - це функціональність у TypeScript, яка дозволяє перевіряти тип змінної або виразу під час виконання програми. Це особливо корисно, коли робота з різними типами даних у різних умовах та функціях може призвести до помилок компіляції або помилок виконання.

TypeScript надає кілька способів Type Guards:

1. typeof: оператор typeof дозволяє перевірити тип змінної під час виконання. Наприклад:
function isString(input: string | number): input is string {
return typeof input === "string";
}

const value: string | number = "Hello";
if (isString(value)) {
console.log(value.toUpperCase());
}

2. instanceof: оператор instanceof перевіряє, чи є об'єкт екземпляром певного класу. Наприклад:
class Person {
name: string;
age: number;
}

class Employee extends Person {
id: number;
position: string;
}

function isEmployee(input: Person): input is Employee {
return input instanceof Employee;
}

const person: Person = new Employee();
if (isEmployee(person)) {
console.log(person.id);
}

3. in: оператор in перевіряє, чи є певна властивість в об'єкті. Наприклад:
interface Circle {
radius: number;
}

interface Square {
side: number;
}

function isCircle(shape: Circle | Square): shape is Circle {
return "radius" in shape;
}

const shape: Circle | Square = { radius: 5 };
if (isCircle(shape)) {
console.log(shape.radius);
}

Type Guards дозволяють писати безпечніший код, що запобігає помилкам під час виконання програми, пов'язані з неправильним використанням типів даних.

#tsquestions
Type Casting (приведення типів) - це функціональність у TypeScript, яка дозволяє явно вказувати компілятору, який тип повинен використовуватися для змінної або виразу у певному контексті.

У TypeScript є два види приведення типів:

1. Angle-bracket Syntax (синтаксис кутових дужок): Цей спосіб полягає у використанні кутових дужок <> та вказівці потрібного типу всередині них. Наприклад:
const myVariable: any = "123";
const stringLength = (<string>myVariable).length;

2. as Syntax (синтаксис as): Цей спосіб полягає у використанні оператора as для приведення типів. Наприклад:
const myVariable: any = "123";
const stringLength = (myVariable as string).length;

Обидва способи приведення типів мають свої переваги та недоліки, але в цілому як syntax більш читабельний і має ширшу підтримку в мові.

Приведення типів часто використовується для роботи з типами даних, які не збігаються з типом змінної або параметром функції, наприклад, для роботи з DOM-елементами або об'єктами API. Однак при використанні типів слід бути обережним, оскільки неправильне використання може призвести до помилок виконання програми.

react:
const input = document.getElementById('inputEmail') as HTMLInputElement;

input.value = 'test@test.ts';


OR

const input = document.getElementById('inputEmail');

if (input) {
(input as HTMLInputElement).value = 'test@test.ts';
}


#tsquestions
Index Properties(властивості-індекси) - це функціональність в TypeScript, яка дозволяє створювати об'єкти з властивостями, що динамічно задаються.

Об'єкти TypeScript можуть мати лише певні властивості, які були оголошені заздалегідь. Однак, при роботі з деякими API або даними, може виникнути необхідність динамічно створюваних властивостей, які не відомі заздалегідь. У цьому випадку можуть допомогти Index Properties.

Для створення Index Properties використовується наступний синтаксис:
interface MyObject {
[key: string]: number;
}


У цьому прикладі ми оголошуємо інтерфейс MyObject, який містить властивості з іменами типу string та значеннями типу number. Ключ [key: string] вказує, що хочемо задати властивості з будь-якими іменами типу string.

Також можна використовувати ключі інших типів, наприклад, числові:
interface MyObject {
[key: number]: string;
}


#tsquestions
Optional Chaining
Це спрощення для перевірок, а чи є поле в об'єкті. Можна для цього використовувати Lodash, а можна механізмом у TS.
interface Person {
name: string;
additionInfo?: {
someInfo: string;
}
}

const user: Person = {
name: 'Alex'
}

console.log(user?.additionInfo?.someInfo);

Ми поставили? перед викликом властивості у якому ми впевнені цим уникли помилки.

#tsquestions
Nullish Coalescing це оператор TypeScript і JavaScript, який дозволяє вибрати значення з двох варіантів, залежно від того, чи є значення "null" або "undefined".

Оператор використовується в наступному синтаксисі:
result = value1 ?? value2;

Тут змінної "result" надається значення "value1", якщо воно не дорівнює "null" або "undefined". Якщо ж "value1" дорівнює "null" або "undefined", то змінній "result" надається значення "value2".

Оператор "??", також відомий як "nullish coalescing operator", відрізняється від оператора "||", який виконує перевірку на хибне значення (falsey), а не лише на "null" або "undefined".

#tsquestions
Перевантаження операторів (function overloads) - це механізм у TypeScript та інших мовах програмування, який дозволяє визначати кілька версій функції або методу з тим самим ім'ям, але різними параметрами і значеннями, що повертаються.

При використанні навантаження операторів компілятор TypeScript вибирає версію функції або методу, яка відповідає типу та кількості переданих параметрів.

Наприклад, припустимо, у нас є функція "sum", яка повинна складати два числа та повертати їхню суму:
function sum(a: number, b: number): number {
return a + b;
}


Ми можемо додати перевантажену версію цієї функції, яка прийматиме рядки замість чисел:
function sum(a: string, b: string): string;
function sum(a: number, b: number): number;
function sum(a: any, b: any): any {
return a + b;
}


У даному випадку ми визначили дві версії функції "sum", які приймають або два числа, або два рядки, і повертають або число, або рядок. Остання версія функції (без параметрів типу) є спільним тілом функції, яке буде виконано, якщо передані параметри не відповідають жодній з перевантажених версій.

При виклику функції "sum" з двома числами буде вибрано відповідну версію функції, яка повертає число. А якщо ми викличемо функцію "sum" з двома рядками, буде вибрано іншу версію функції, яка повертає рядок.

Перевантаження операторів може бути корисним у випадках, коли необхідно обробляти різні типи даних в одній функції або методі. Вона також може покращити читабельність та підтримуваність коду.

#tsquestions
Generic function/method

function merge<T, U>(objA: T, objB: U) {
return Object.assign(objA, objB);
}

const merged = merge({name: 'Alisa'}, {age: 28});

merged.name;


function identity<T>(arg: T): T {
return arg;
}

let output1 = identity<string>("hello"); // output1 типу string
let output2 = identity<number>(123); // output2 типу number

У цьому прикладі метод identity є generic-методом, оскільки він може приймати будь-який тип T як вхідний параметр і повертати його як вихідний параметр. Під час виклику методу identity тип параметра T буде вирішуватися автоматично на основі переданого значення. Наприклад:

#tsquestions
Ключове слово extends використовується в узагальненому типі (generic type) для визначення обмеження на тип даних, який може бути переданий як параметр типу.

Розглянемо наступний приклад:
function getObjectProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}

У цьому прикладі T і K - це параметри типу. Параметр T може бути будь-яким типом даних, а параметр K це узагальнений тип, який обмежений типом властивості об'єкта T.

Тут extends використовується обмеження типу параметра K лише тими властивостями T, які є ключами (keyof) об'єкта T. Таким чином, при спробі передати некоректний ключ, TypeScript видасть помилку компіляції.

Також extends можна використовувати для обмеження узагальненого типу будь-яким іншим типом, наприклад:
interface Fruit {
name: string;
color: string;
}

function getFruit<T extends Fruit>(fruit: T) {
return `${fruit.name} (${fruit.color})`;
}
У цьому прикладі T обмежений інтерфейсом Fruit. Це означає, що параметр fruit має бути об'єктом, що має властивості name та color типу string.

Таким чином, extends використовується в узагальнених типах для визначення обмежень на типи даних, які можуть бути передані як параметри типів.

interface Animal {
name: string;
}

function printName<T extends Animal>(animal: T) {
console.log(animal.name);
}

const cat: Animal = { name: 'Fluffy' };
printName(cat); // Виведе 'Fluffy'

const dog = { name: 'Buddy', breed: 'Golden Retriever' };
printName(dog); // Помилка компіляції, оскільки об'єкт dog відповідає інтерфейсу Animal
Ще приклад, що показає, що є така властивість:

function printLength<T extends { length: number }>(obj: T) {
console.log(obj.length);
}

const array = [1, 2, 3];
printLength(array); // Виводить 3, оскільки масив має властивість length

const string = 'Hello';
printLength(string); // Виводить 5, тому що рядок має властивість length

const number = 42;
printLength(number); // Помилка компіляції, тому що число не має властивості length

#tsquestions
keyof — дозволяє зробити уточнення, що якийсь тип є ключем в об'єкті.
function extractValue<T extends object, U extends keyof T> (obj:T, key:U) {
return obj[key];
}

extractValue({name: 'Sergei'}, 'name');


За допомогою U extends keyof T ми зробили уточнення, що тип U є як ключ у типі T і тепер усе працює.

#tsquestions
Ми можемо призначити дженерики на клас, це буває зручно, якщо ми хочемо позначити тип, який пронизуватиме весь клас.
class StoreClass<T> {
private data: T[] = [];

addItem (item:T):void {
this.data.push(item);
}

getItems (): T[] {
return this.data;
}
}

І тепер ми можемо контролювати які типи можуть зберігатися як data;
const store = new StoreClass<string>();

store.addItem('test');

#tsquestions
Utility Types - це вбудовані в TypeScript типи, які надають корисні функції для маніпулювання із типами даних. Давайте розглянемо три з них - Partial, Readonly і Pick:

1. Partial - цей тип дозволяє зробити всі властивості об'єкта необов'язковими, зробивши їх опціональними. Ось приклад використання:
interface User {
name: string;
age: number;
email: string;
}

function updateUser(user: User, dataToUpdate: Partial<User>): User {
return { ...user, ...dataToUpdate };
}

const user: User = { name: 'John', age: 25, email: 'john@example.com' };

const updatedUser = updateUser(user, { age: 26, email: 'new-email@example.com' });
console.log(updatedUser);
// Output: { name: 'John', age: 26, email: 'new-email@example.com' }
У цьому прикладі функція updateUser приймає об'єкт користувача та об'єкт, що містить дані для оновлення, за допомогою Partial<User>. Це дозволяє передавати тільки певні властивості для оновлення, а решта залишаються незмінними.

2. Readonly - цей тип дозволяє зробити всі властивості об'єкта не змінюваними, тобто вони стають тільки для читання. Ось приклад використання:
interface User {
readonly name: string;
readonly age: number;
}

const user: Readonly<User> = { name: 'John', age: 25 };

// Помилка компіляції, не можна змінювати значення поля name
user.name = 'Jane';

// Помилка компіляції, не можна додавати нові поля
user.email = 'john@example.com';

У цьому прикладі ми визначаємо об'єкт користувача з допомогою Readonly<User>. Це дозволяє зробити всі властивості об'єкта тільки для читання, тобто не можна змінювати їх значення після того, як об'єкт був створений.

3. Pick - це один з utility типів в TypeScript, який дозволяє створити новий тип, який містить тільки вибрані властивості з існуючого типу.

Наприклад, ми маємо інтерфейс User з властивостями name і age:
interface User {
name: string;
age: number;
}


Ми можемо створити новий тип, що містить лише властивість name з інтерфейсу User, використовуючи тип Pick:
type UserNameOnly = Pick<User, 'name'>;

Тепер тип UserNameOnly буде мати лише одну властивість name, яка є рядком:
const user: UserNameOnly = { name: 'John' };


Отже, тип Pick дозволяє зробити новий тип з вибраних властивостей іншого типу, що може бути корисним у багатьох випадках в програмуванні.

#tsquestions
Декоратори - це механізм у мовах програмування, таких як TypeScript, JavaScript, Java та інших, що дозволяє обернути функцію, клас або інший об'єкт в іншу функцію, яка змінює його поведінку або додає додаткову функціональність. Декоратори надають гнучкість у додаванні та зміні поведінки коду без необхідності модифікувати його безпосередньо.

Ідея декораторів полягає в тому, що ви можете взяти існуючу функцію або клас і обернути її в іншу функцію, яка виконує певні дії перед або після виклику вихідної функції, або в процесі виконання. При цьому код, що викликає, і сама обернута функція не помічають різниці.

Переваги використання декораторів включають:

1. Модульність та повторне використання коду: Ви можете створювати невеликі декоратори, які вирішують конкретні завдання, а потім комбінувати їх для створення складної поведінки. Це дозволяє легко повторно використовувати код і робить його більш модульним.

2. Розширюваність та гнучкість: Декоратори дозволяють додавати функціональність до існуючого коду без необхідності зміни. Ви можете легко додавати нові декоратори або змінювати порядок застосування існуючих, щоб отримати потрібну поведінку.

3. Поділ відповідальності: Декоратори дозволяють розділяти логіку та відповідальність між різними компонентами коду. Ви можете створювати декоратори, що відповідають за логування, автентифікацію, кешування та інші аспекти функціональності, а потім застосовувати їх до відповідних об'єктів чи функцій.

Приклади використання декораторів можна знайти у різних галузях розробки програмного забезпечення. У React, наприклад, декоратори (звані High Order Components) використовуються додавання додаткової логіки до компонентів. У Node.js, middleware (які також є декораторами) використовуються для обробки проміжних етапів запитів. У TypeScript декоратори можуть застосовуватися до класів, методів, властивостей та параметрів для додавання аспектів, таких як логування, валідація та серіалізація.

Важливо, що декоратори TypeScript зазвичай використовуються за допомогою синтаксису @ім'яДекоратора, який дозволяє застосовувати декоратори до певних елементів коду, таким як класи, методи і властивості, за допомогою явного вказівки декоратора перед визначенням елемента. Це спрощує використання та розуміння декораторів у коді.

Коли компілятор зустрічає @ то він шукає функцію з ім'ям, вказаним після @, обертає в неї те, що наступним рядком: передає в неї відповідні аргументи і забезпечує виклик обгорнутої функції з усіма аргументами виклику після відпрацювання обгортки, за умови, що з неї повернувся undefined.

#tsquestions
https://www.w3schools.com/typescript/exercise.php

Хороший сайт по тренуванню навичкам по TypeScript. Швидко можна освіжити знання чи вивчити нове щось.