M3 | WebDev
103 subscribers
105 photos
4 videos
14 links
Your guide to the world of programming 🌐🚀
Download Telegram
На днях на LinkedIn появилась публикация от старшего менеджера по продуктам в Amazon, который проработал в компании 1,5 года, практически ничего не делая. Вот ключевые моменты:

📉 Перешел в Amazon после увольнения из Google с намерением «ничего не делать», получать деньги и в конечном итоге попасть под сокращение.

🛠 За все это время он:
• Выполнил одну цель.
• Разобрал семь тикетов.
• Создал автоматизированную панель, на разработку которой ушло 3 дня (хотя заявил, что это заняло три месяца).

🚫 Его основная работа заключалась в отказе другим командам в интеграции, предоставляя им возможность выполнять 95% работы самостоятельно.

Сейчас он задается вопросом, сколько времени ему еще удастся так продержаться.

🤔 Интересно, сколько бы вы ему дали?
🎯 Основные уязвимости при разработке на чистом HTML + JS и как их минимизировать с помощью Vue и React

Если вы разрабатываете на чистом HTML и JavaScript, обратите внимание на следующие уязвимости:

XSS (Cross-Site Scripting): Вредоносный код на странице. Решение: Vue и React автоматически экранируют данные, снижая риск XSS-атак. Но избегайте использования небезопасных методов, таких как v-html или dangerouslySetInnerHTML.

CSRF (Cross-Site Request Forgery): Опасные действия от имени пользователя. Решение: Vue и React облегчают внедрение CSRF-токенов, но защита зависит от правильной настройки сервера.

Инъекции через URL и параметры запроса: Риск передачи вредоносных данных. Решение: Встроенные роутеры позволяют безопасно обрабатывать маршруты, но нужна дополнительная защита на сервере.

Управление состоянием и утечка данных: Проблемы с состоянием в больших приложениях. Решение: Использование Vuex или Redux помогает структурировать данные и минимизировать ошибки, но безопасность данных зависит от общей архитектуры.

Повторное использование кода и безопасность компонентов: Дублирование кода ведет к ошибкам. Решение: Компонентный подход позволяет создавать повторно используемые и безопасные элементы, но важно продумывать безопасность на этапе разработки.

Отсутствие защиты на уровне UI: Ошибки взаимодействия с интерфейсом. Решение: Vue и React предлагают инструменты для безопасного взаимодействия с пользователем, но корректная реализация — на вашей ответственности.

Vue и React облегчают внедрение мер безопасности, но полная защита требует комплексного подхода и грамотного использования фреймворков.

👨‍💻 Выбирайте фреймворки, которые помогут вам минимизировать риски и упростить разработку!
Идеальная карьера для айтишника выглядит так :
🔄 Event Loop в JavaScript

Event Loop — это механизм, который позволяет JavaScript работать с неблокирующей моделью ввода-вывода. Хотя Event Loop не является частью самого JavaScript, его реализация зависит от среды, в которой выполняется код (например, браузер или Node.js). Однако, несмотря на различия в реализации, цель Event Loop везде одна — управление асинхронными задачами.

Основные компоненты:

1. Call Stack (Стек вызовов): В нем выполняются функции в порядке LIFO (Last In, First Out). Когда функция вызывает другую функцию, она добавляется на вершину стека. Когда выполнение функции завершается, она удаляется из стека. Если стек пуст, Event Loop начинает извлекать задачи из очереди.

2. Task Queue (Очередь задач): Это очередь, куда попадают асинхронные задачи, такие как колбэки, промисы и другие операции, которые не могут быть выполнены немедленно. Когда стек вызовов становится пустым, Event Loop берет первую задачу из этой очереди и помещает ее в стек вызовов для выполнения.

3. Web API: Это интерфейсы, предоставляемые окружением (например, браузером), такие как setTimeout, DOM events, XHR и т.д. Эти API не входят в спецификацию JavaScript, но они обеспечивают взаимодействие с Call Stack и Task Queue через Event Loop.

Важные детали:

Task Queue делится на два типа очередей :

- Microtask Queue: Помимо обычной очереди задач, существует отдельная очередь для микрозадач, таких как Promise. Microtask Queue имеет более высокий приоритет, чем обычная Task Queue, и обрабатывается Event Loop сразу после выполнения всех синхронных операций и до начала выполнения макрозадач.

- Macrotask Queue: В эту очередь попадают такие задачи, как таймеры, события, AJAX-запросы и другие макрозадачи. Они обрабатываются после выполнения всех микрозадач.

Взаимодействие между компонентами:

1. Выполнение синхронного кода: Все синхронные операции выполняются в Call Stack. Например, вызов функции и ее выполнение.

2. Взаимодействие с Web API: При вызове асинхронных функций, таких как setTimeout, браузер или Node.js перемещают их в Web API, где они ждут своего завершения.

3. Добавление задач в очередь: Как только асинхронная операция завершается (например, таймер истекает), соответствующий колбэк перемещается в Macrotask Queue или Microtask Queue, в зависимости от типа задачи.

4. Обработка задач Event Loop: Event Loop проверяет, есть ли задачи в Microtask Queue и Macrotask Queue. Сначала выполняются все задачи из Microtask Queue, затем Event Loop переходит к задачам из Macrotask Queue.

Пример работы Event Loop:
console.log('Start'); // 1

setTimeout(() => {
console.log('Timeout'); // 4
}, 0);

Promise.resolve().then(() => {
console.log('Promise'); // 3
});

console.log('End'); // 2

Последовательность выполнения:
1. Выполняется первый console.log('Start') и выводится в консоль.
2. Вызов setTimeout передает колбэк в Web API, где он ожидает выполнения.
3. Промис перемещает свой колбэк в Microtask Queue.
4. Выполняется второй console.log('End').
5. Event Loop проверяет Microtask Queue, видит там колбэк промиса и выполняет его.
6. После выполнения всех микрозадач, Event Loop переходит к Task Queue и выполняет колбэк из setTimeout.

Результат в консоли:
StartEndPromiseTimeout

Заключение:
Event Loop — это механизм, который поддерживает однопоточность JavaScript, управляя асинхронными задачами и обеспечивая выполнение операций в правильной последовательности. Это позволяет JavaScript эффективно обрабатывать пользовательские события, запросы к серверу и другие задачи, не блокируя основной поток выполнения.

Такое глубокое понимание Event Loop помогает писать более эффективный код и лучше разбираться в особенностях работы JavaScript. 🚀

Тэги : #javascript
🌟 Понимаем конструкцию `try...catch` и оператор `throw` в JavaScript 🌟

В JavaScript обработка ошибок выполняется с помощью конструкции try...catch и оператора throw. Давайте разберемся в деталях!

🔄 Конструкция try...catch

- Блок `try`: Здесь размещается код, в котором потенциально может возникнуть ошибка.
- Блок `catch`: Если в блоке try произошла ошибка, исполнение передается в блок catch. Здесь мы можем обработать ошибку и принять меры для продолжения работы приложения.

try {
// Код, который может вызвать ошибку
let data = JSON.parse('{"name": "John"}');
} catch (error) {
console.error("Ошибка: " + error.message);
}


💥 Оператор throw

Если необходимо намеренно создать ошибку, используется оператор throw. Это полезно, когда нужно остановить выполнение кода при возникновении определенных условий.

function divide(a, b) {
if (b === 0) {
throw new Error("Деление на ноль невозможно!");
}
return a / b;
}

try {
let result = divide(10, 0);
} catch (error) {
console.error("Произошла ошибка: " + error.message);
}


🛠 Объект Error

Когда возникает ошибка, создается объект Error, содержащий информацию об ошибке:
- `error.message`: Текст ошибки.
- `error.name`: Имя ошибки (например, TypeError, ReferenceError).
- `error.stack`: Стек вызовов, указывающий путь выполнения кода до места возникновения ошибки.

📚 Кастомные ошибки

Вы можете создать свои собственные ошибки, расширяя класс Error:

class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}

try {
throw new CustomError("Это моя собственная ошибка!");
} catch (error) {
console.error(`${error.name}: ${error.message}`);
}


Когда использовать?

1. Валидация данных: Убедитесь, что передаваемые данные соответствуют ожиданиям.
2. Асинхронные операции: Обработайте ошибки, возникающие при работе с промисами или асинхронными вызовами.
3. Неожиданные состояния: Выявляйте и обрабатывайте состояния, которые не должны возникать в нормальных условиях.

🚀 Заключение

Использование try...catch, throw, и объекта Error помогает сделать код более надежным, предсказуемым и легким для отладки. Обработка ошибок — это залог создания стабильных приложений! 💻
🚀 Базовое Понимание и Возможности Классов в JavaScript

В JavaScript классы появились в ES6 и предоставляют новый способ работы с объектами, однако под капотом классы — это всё ещё функции. Классы упрощают создание объектов, наследование и использование методов, делая код более понятным и структурированным. Давайте рассмотрим основные аспекты работы с классами.

📚 Базовый синтаксис класса

Класс объявляется с использованием ключевого слова class, после которого следует имя класса. Внутри класса можно объявить методы. Например:

class User {
constructor(name) {
this.name = name;
}

sayHi() {
console.log(`Привет, я ${this.name}!`);
}
}

const user = new User('Иван');
user.sayHi(); // Привет, я Иван!

Здесь constructor — это специальный метод, который вызывается при создании нового объекта через new. Внутри конструктора определяются свойства объекта.

🧬 Наследование классов

В JavaScript классы поддерживают наследование. Для этого используется ключевое слово extends, которое позволяет одному классу наследовать методы и свойства другого.

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

speak() {
console.log(`${this.name} издает звук.`);
}
}

class Dog extends Animal {
speak() {
console.log(`${this.name} лает.`);
}
}

const dog = new Dog('Барбос');
dog.speak(); // Барбос лает.

📊 Статические свойства и методы

Статические методы и свойства принадлежат классу, а не его экземплярам. Они определяются с помощью ключевого слова static.

class MathUtils {
static square(x) {
return x * x;
}
}

console.log(MathUtils.square(4)); // 16

🔒 Приватные и защищённые методы и свойства

С появлением ES2022 в JavaScript были введены приватные свойства и методы, которые начинаются с символа #. Такие свойства и методы доступны только внутри класса.

class User {
#password;

constructor(name, password) {
this.name = name;
this.#password = password;
}

checkPassword(password) {
return this.#password === password;
}
}

const user = new User('Иван', '1234');
console.log(user.checkPassword('1234')); // true

🔧 Расширение встроенных классов

Вы можете расширять встроенные классы JavaScript, такие как Array, добавляя собственные методы.

class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}
}

const arr = new PowerArray(1, 2, 3);
console.log(arr.isEmpty()); // false

🔍 Проверка класса: "instanceof"

Оператор instanceof используется для проверки, принадлежит ли объект определённому классу или его наследнику.

console.log(arr instanceof PowerArray); // true

🧩 Примеси

Примеси позволяют разделять функциональность между классами. В JavaScript примеси реализуются через простое добавление методов в прототип класса.

let sayHiMixin = {
sayHi() {
console.log(`Привет, ${this.name}`);
}
};

class User {
constructor(name) {
this.name = name;
}
}

Object.assign(User.prototype, sayHiMixin);

const user = new User('Иван');
user.sayHi(); // Привет, Иван

🧭 Заключение:

Классы в JavaScript делают код более чистым и позволяют легко создавать сложные архитектуры, оставаясь при этом гибкими и мощными. Используйте их, чтобы создавать иерархии объектов, организовывать повторно используемые компоненты и улучшать читаемость кода.

Тэги : #javascript
🎉 Что будет выведено а консоль?
Anonymous Quiz
47%
Hello!, Hello!
27%
Hello!, TypeError
20%
TypeError, Hello
7%
Ошибка
🚀 Базовые Принципы ООП

Классы в JavaScript предоставляют мощные инструменты для организации и структурирования кода, используя ключевые принципы объектно-ориентированного программирования (ООП). Давайте разберём основные из них.

🛡 Инкапсуляция

Инкапсуляция заключается в скрытии внутренней реализации объекта, предоставляя только необходимый интерфейс для взаимодействия с ним. Это позволяет защитить данные и поддерживать код в чистоте.

Пример был показан в предыдущим посту .

🧬 Наследование

Наследование позволяет одному классу (подклассу) унаследовать свойства и методы другого класса (родительского), расширяя и переопределяя их при необходимости. Это помогает избегать дублирования кода.

Пример был показан в предыдущим посту .

🎭 Полиморфизм

Полиморфизм позволяет методам, с одинаковыми именами в разных классах, работать по-разному в зависимости от объекта. Это позволяет создавать более гибкие и расширяемые структуры.

Пример:

class Animal {
speak() {
console.log('Животное издает звук.');
}
}

class Dog extends Animal {
speak() {
console.log('Собака лает.');
}
}

class Cat extends Animal {
speak() {
console.log('Кошка мяукает.');
}
}

const animals = [new Dog(), new Cat()];
animals.forEach(animal => animal.speak());
// Собака лает.
// Кошка мяукает.

🔗 Внедрение зависимостей (Dependency Injection)

Внедрение зависимостей — это паттерн, который позволяет передавать зависимости (например, объекты или службы) в конструктор класса, что делает классы более гибкими и тестируемыми.

Пример:

class Engine {
start() {
console.log('Двигатель запущен');
}
}

class Car {
constructor(engine) {
this.engine = engine;
}

drive() {
this.engine.start();
console.log('Машина едет');
}
}

const engine = new Engine();
const car = new Car(engine);
car.drive();
// Двигатель запущен
// Машина едет

🧩 Абстракция

Абстракция
— это принцип ООП, который позволяет выделить только важные детали и скрыть сложные внутренние механизмы.

class CoffeeMachine {
makeCoffee() {
this.#boilWater();
this.#brewCoffee();
this.#pourInCup();
console.log('Coffee is ready!');
}

#boilWater() {
console.log('Boiling water...');
}

#brewCoffee() {
console.log('Brewing coffee...');
}

#pourInCup() {
console.log('Pouring coffee into cup...');
}
}

const myCoffeeMachine = new CoffeeMachine();
myCoffeeMachine.makeCoffee();

📄 Интерфейсы (в контексте TypeScript)

Хотя в чистом JavaScript интерфейсы отсутствуют, в TypeScript они позволяют определять структуру объектов, задавая обязательные методы и свойства для классов, которые их реализуют.

Пример:

interface Drivable {
drive(): void;
}

class Car implements Drivable {
drive() {
console.log('Машина едет');
}
}

const car = new Car();
car.drive(); // Машина едет

🧭 Заключение:

📢 Эти принципы помогают создавать мощные и гибкие архитектуры, которые легко поддерживать и расширять. Начните использовать их в своём коде, и вы почувствуете, как он становится более структурированным и понятным! А следующий пост будет про приципы SOLID 🚀

Тэги : #javascript
🔥 SOLID Принципы в JavaScript 🚀

SOLID — это набор из пяти принципов, которые помогают писать понятный, поддерживаемый и расширяемый код в объектно-ориентированном программировании (ООП). Давайте разберём каждый принцип с примерами на JavaScript!


1️⃣ Single Responsibility Principle (SRP) — Принцип единственной ответственности

Каждый класс должен иметь одну ответственность.

class User {
constructor(name) {
this.name = name;
}
}

class UserRepository {
save(user) {
// Сохраняет пользователя в БД
}
}

Здесь User отвечает за данные пользователя, а UserRepository — за сохранение данных. 📝


2️⃣ Open/Closed Principle (OCP) — Принцип открытости/закрытости

Классы должны быть открыты для расширения, но закрыты для изменения. Например, добавляем новые фигуры, не меняя существующий код:

class Shape {
area() {
throw 'Метод должен быть реализован';
}
}

class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}

area() {
return Math.PI * this.radius * this.radius;
}
}

Вы можете добавить новый класс Square, не меняя код Circle или Shape. ⭕️🔲


3️⃣ Liskov Substitution Principle (LSP) — Принцип подстановки Барбары Лисков

Подклассы должны заменять базовые классы без ошибок. Это означает, что любой экземпляр подкласса должен быть возможной заменой экземпляра родительского класса.

class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}

area() {
return this.width * this.height;
}
}

class Square extends Rectangle {
constructor(side) {
super(side, side);
}
}

Экземпляр Square может заменить Rectangle и будет работать корректно. 🟦➡️🟥

4️⃣ Interface Segregation Principle (ISP) — Принцип разделения интерфейса

Лучше много маленьких интерфейсов, чем один большой. Пример на TS :

interface Printer {
print(doc: string): void;
}

interface Scanner {
scan(): string;
}

class MultiFunctionDevice implements Printer, Scanner {
print(doc: string) {
console.log(`Печать документа: ${doc}`);
}

scan() {
return 'Документ отсканирован';
}
}

💡 Реализуйте только необходимые интерфейсы.


5️⃣ Dependency Inversion Principle (DIP) — Принцип инверсии зависимостей

Высокоуровневые модули не зависят от низкоуровневых, оба зависят от абстракций.

class MySQLConnection {
connect() {
console.log('Подключение к MySQL');
}
}

class MongoDBConnection {
connect() {
console.log('Подключение к MongoDB');
}
}

class UserRepository {
constructor(dbConnection) {
this.dbConnection = dbConnection;
}

connect() {
this.dbConnection.connect();
}
}

const userRepository = new UserRepository(new MySQLConnection());
userRepository.connect();

Здесь UserRepository зависит от абстракции подключения к БД, а не от конкретной реализации, что упрощает замену БД. 🛠


⚙️ Применение SOLID принципов помогает создавать гибкие и поддерживаемые приложения! Используйте их, чтобы ваш код стал прочным, как камень! 💪🔥

Тэги : #javascript
💡 Всё о Web-хранилищах: `localStorage`, `sessionStorage` и `Cookies`

Веб-хранилища в JavaScript помогают сохранять данные прямо в браузере пользователя. Разберём, что из них чем отличается и где используется.

1️⃣ localStorage

- 💾 Хранение: Данные сохраняются без ограничения по времени. Даже после закрытия браузера данные останутся.
- 📦 Вместимость: Обычно около 5-10 МБ на домен.
- 📌 Применение: Подходит для хранения пользовательских настроек, корзины покупок и других данных, которые нужно сохранять между сессиями.

2️⃣ sessionStorage

- Хранение: Данные сохраняются только на время сессии. Закроете вкладку — данные исчезнут.
- 📦 Вместимость: Аналогично localStorage, но тоже около 5-10 МБ.
- 📌 Применение: Используется для временных данных, которые нужны только на время работы с одной вкладкой, например, для состояния UI или промежуточных данных форм.

3️⃣ Cookies

- 🍪 Хранение: Данные хранятся до указанного времени истечения или пока не будут удалены. Могут передаваться на сервер при каждом запросе.
- 📦 Вместимость: Обычно до 4 КБ.
- 🔒 Заголовки: Настройки безопасности и срока действия задаются с помощью заголовков Set-Cookie и атрибутов Secure, HttpOnly, SameSite.
- 📌 Применение: Идеальны для авторизации, хранения сессий пользователя и других данных, которые должны передаваться между клиентом и сервером.

🛠 Когда и что использовать?
- `localStorage` — для данных, которые нужно сохранять на долгий срок.
- `sessionStorage` — для данных, которые нужны на время сессии.
- `Cookies` — для данных, которые должны передаваться между клиентом и сервером.

💻 Пример использования:

javascript
// localStorage
// Сохранение данных
localStorage.setItem('username', 'John');

// Получение данных
const user = localStorage.getItem('username');
console.log(user); // 'John'

// Удаление данных
localStorage.removeItem('username');

// Очистка всего хранилища
localStorage.clear();

// sessionStorage
// Сохранение данных на время сессии
sessionStorage.setItem('sessionID', '12345');

// Получение данных
const session = sessionStorage.getItem('sessionID');
console.log(session); // '12345'

// Удаление данных
sessionStorage.removeItem('sessionID');

// Очистка всего сессионного хранилища
sessionStorage.clear();

// Cookies
// Создание куки
document.cookie = "theme=dark; max-age=3600; path=/";

// Получение всех куки
console.log(document.cookie); // 'theme=dark'

// Удаление куки
document.cookie = "theme=; max-age=0; path=/";

Заключение: Правильный выбор веб-хранилища помогает улучшить производительность и удобство использования веб-приложений. 🚀
🎯 Какой тип веб-хранилища передаётся на сервер с каждым HTTP-запросом? 🎯
Anonymous Quiz
8%
localStorage
0%
sessionStorage
85%
Cookies
8%
Все перечисленные
📜 Свойства объекта в JavaScript и их конфигурация

Свойства объектов в JavaScript не ограничиваются только значениями. Они обладают флагами и могут быть геттерами/сеттерами. Давайте разберемся, как это работает.

🔍 Флаги и дескрипторы свойств

Когда создается объект, его свойства имеют три базовых флага:

1. writable: Если true, значение свойства можно изменять.
2. enumerable: Если true, свойство участвует в перечислении через циклы (for...in) или методы (Object.keys).
3. configurable: Если true, свойство можно удалить, а также изменять его флаги.

Флаги задаются при помощи дескрипторов. По умолчанию все флаги имеют значение true.

🛠 Пример использования флагов

const car = { brand: "Toyota" };

Object.defineProperty(car, 'brand', {
writable: false,
enumerable: false,
configurable: false
});

// Теперь свойства "brand" не будет видно в циклах и его нельзя изменить или удалить.
console.log(car.brand); // Toyota
car.brand = "Honda"; // Ошибка: свойство недоступно для изменения


Для получения дескрипторов свойств используется Object.getOwnPropertyDescriptor:

let descriptor = Object.getOwnPropertyDescriptor(car, 'brand');
console.log(descriptor);
// Вывод: { value: 'Toyota', writable: false, enumerable: false, configurable: false }


🛠 Свойства — геттеры и сеттеры

Геттеры и сеттеры позволяют управлять доступом к свойствам объектов, добавляя дополнительные проверки, вычисления или логику.

- Геттер (get): возвращает значение при обращении к свойству.
- Сеттер (set): вызывается при установке значения свойства.

🛠 Пример геттеров и сеттеров

const person = {
firstName: 'Alice',
lastName: 'Johnson',

get fullName() {
return `${this.firstName} ${this.lastName}`;
},

set fullName(value) {
[this.firstName, this.lastName] = value.split(' ');
}
};

console.log(person.fullName); // Alice Johnson
person.fullName = 'John Doe';
console.log(person.firstName); // John
console.log(person.lastName); // Doe


В этом примере, при присвоении person.fullName у нас автоматически устанавливаются firstName и lastName.

📋 Практические случаи применения:

1. Контроль доступа: Изменение writable позволяет защитить важные данные от случайных изменений.
2. Настраиваемое поведение: Использование геттеров и сеттеров упрощает работу с данными, добавляя возможность валидации или форматирования.
3. Оптимизация производительности: Отключение enumerable для некоторых свойств помогает скрыть их в циклах или при копировании объектов.

📊 Сводка: В чем преимущества?

- 📌 Безопасность данных: Защита свойств от изменений или удаления.
- 📌 Гибкость: Настраиваемое поведение при чтении и записи.
- 📌 Удобство работы с объектами: Легкость реализации вычисляемых свойств и контроля за доступом.

Изучение свойств и их конфигурации поможет глубже понять JavaScript и писать более чистый и защищенный код! 🎉

Тэги : #javascript