CSS (Cascading Style Sheets) появился в середине 1990-х годов как стандарт для описания внешнего вида и форматирования веб-страниц. Разработка CSS началась как ответ на необходимость разделения содержимого веб-страниц и их оформления, что улучшило бы управляемость и поддерживаемость веб-контента. Рассмотрим подробнее историю и развитие CSS.
Ранние годы веб-разработки (1991-1994):
<b>
, <i>
, <font>
и другие.Необходимость стандартизации (1994-1996):
Создание стандарта CSS (1996):
Развитие CSS (1998 - настоящее время):
CSS1 (1996):
CSS2 (1998):
CSS3 (начало 2000-х):
В CSS4 (официальной спецификации CSS4 как таковой нет, но многие новые возможности продолжают разрабатываться в рамках модулей CSS3) включены современные инструменты для веб-разработки, такие как переменные (CSS Custom Properties), сложные селекторы, улучшенная типографика и адаптивный дизайн.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример CSS</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>Заголовок страницы</h1>
</header>
<main>
<p>Это пример абзаца текста.</p>
</main>
<footer>
<p>© 2024 Все права защищены.</p>
</footer>
</body>
</html>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35😁4❤3
Anonymous Quiz
14%
"undefined"
32%
"number"
24%
"object"
30%
"NaN"
👍34
Redux — это библиотека для управления состоянием приложений, часто используемая с React, но она также может быть использована с другими библиотеками или фреймворками JavaScript. Redux предлагает централизованное хранилище (store) для состояния приложения, что делает управление состоянием более предсказуемым и удобным. Рассмотрим основные преимущества использования Redux:
Для начала установим необходимые пакеты:
npm install redux react-redux
Создание действий (actions)
// actions.js
export const increment = () => ({
type: 'INCREMENT',
});
export const decrement = () => ({
type: 'DECREMENT',
});
Создание редюсера (reducer)
// reducer.js
const initialState = {
count: 0,
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + 1,
};
case 'DECREMENT':
return {
...state,
count: state.count - 1,
};
default:
return state;
}
};
export default counterReducer;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤2🤯1
Anonymous Quiz
4%
continue
84%
break
11%
return
1%
exit
👍4❤1😁1
Redux работает по трем основным принципам: единое хранилище для всего состояния приложения, изменения в состоянии возможны только через отправку действий, и редукторы — чистые функции, определяющие, как действия изменяют состояние.
Все состояние приложения хранится в одном объекте хранилища (store). Это обеспечивает централизованное управление состоянием, что упрощает отладку и тестирование. В приложении должно быть только одно хранилище.
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
Единственный способ изменить состояние — это отправить действие (action), описывающее изменение. Действия — это простые объекты, которые имеют свойство
type
и, возможно, дополнительные данные. Изменения состояния должны происходить только через действия.const increment = () => ({
type: 'INCREMENT',
});
store.dispatch(increment());
Для описания того, как действия изменяют состояние, используются редюсеры (reducers). Редюсеры — это чистые функции, которые принимают предыдущее состояние и действие в качестве аргументов и возвращают новое состояние. Редюсеры должны быть чистыми функциями и не должны иметь побочных эффектов.
const initialState = {
count: 0,
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + 1,
};
case 'DECREMENT':
return {
...state,
count: state.count - 1,
};
default:
return state;
}
};
const store = createStore(counterReducer);
Состояние в Redux должно быть неизменяемым. Вместо изменения текущего состояния, редюсеры должны возвращать новые объекты состояния. Используйте методы, которые не изменяют исходные объекты, такие как
Array.prototype.map
, Array.prototype.filter
, и оператор распространения (spread operator) для создания новых объектов и массивов.const newState = {
...state,
count: state.count + 1,
};
Для упрощения отладки и поддержки инструментов разработки (например, Redux DevTools), действия и состояния должны быть сериализуемыми (не содержать циклических ссылок и неподдерживаемых типов данных, таких как функции или символы).
const action = {
type: 'ADD_TODO',
payload: {
id: 1,
text: 'Learn Redux',
},
};
const initialState = {
todos: {
byId: {
1: { id: 1, text: 'Learn Redux' },
2: { id: 2, text: 'Build an app' },
},
allIds: [1, 2],
},
};
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22❤2
Anonymous Quiz
21%
Массив значений свойств объекта
73%
Массив имен свойств объекта
4%
Количество свойств объекта
2%
Новый объект с теми же свойствами
👍17
Чтобы изменить данные, нужно выполнить несколько шагов: создать действие (action), определить редюсер (reducer), который будет обрабатывать это действие и обновлять состояние, и затем отправить действие (dispatch action) в хранилище. Рассмотрим эти шаги более подробно.
Это объект, который описывает, что должно произойти. Он должен содержать как минимум свойство
type
, которое указывает на тип действия. Дополнительно можно добавить любые данные, которые нужны для обновления состояния.// actions.js
export const increment = () => ({
type: 'INCREMENT',
});
export const decrement = () => ({
type: 'DECREMENT',
});
export const setValue = (value) => ({
type: 'SET_VALUE',
payload: value,
});
Это чистая функция, которая принимает текущее состояние и действие, а затем возвращает новое состояние. Редюсер должен быть чистой функцией, то есть не изменять переданные аргументы и не иметь побочных эффектов.
// reducer.js
const initialState = {
count: 0,
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + 1,
};
case 'DECREMENT':
return {
...state,
count: state.count - 1,
};
case 'SET_VALUE':
return {
...state,
count: action.payload,
};
default:
return state;
}
};
export default counterReducer;
createStore
из библиотеки Redux. Хранилище объединяет редюсеры и обеспечивает централизованное управление состоянием.// store.js
import { createStore } from 'redux';
import counterReducer from './reducer';
const store = createStore(counterReducer);
export default store;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
useSelector
и useDispatch
из библиотеки react-redux
.// App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, setValue } from './actions';
const App = () => {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
<button onClick={() => dispatch(setValue(10))}>Set to 10</button>
</div>
);
};
export default App;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29❤3
👍11😁6
Есть несколько способов развернуть строку. Один из наиболее распространенных способов — это преобразование строки в массив, разворот массива и затем преобразование массива обратно в строку.
Использование методов массива split, reverse и join
Преобразование строки в массив символов с помощью
split('').
Разворот массива с помощьюпросят с веро
Преобразование массива обратно в строку с помощью
join('').
function reverseString(str) {
return str.split('').reverse().join('');
}
console.log(reverseString('hello')); // 'olleh'
Использование цикла for
Создание пустой строки для результата.
Проход по исходной строке с конца к началу и добавление каждого символа в результат.
function reverseString(str) {
let reversed = '';
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
console.log(reverseString('hello')); // 'olleh'
Использование рекурсии
Рекурсивное разбиение строки и объединение символов в обратном порядке.
function reverseString(str) {
if (str === '') {
return '';
} else {
return reverseString(str.substr(1)) + str[0];
}
}
console.log(reverseString('hello')); // 'olleh'
Использование деструктуризации и метода reduce
Преобразование строки в массив с помощью оператора распространения (
spread operator
)function reverseString(str) {
return [...str].reduce((acc, char) => char + acc, '');
}
console.log(reverseString('hello')); // 'olleh'
Использование Array.from и reduceRight
Преобразование строки в массив с помощью
Array.from.
function reverseString(str) {
return Array.from(str).reduceRight((acc, char) => acc + char, '');
}
console.log(reverseString('hello')); // 'olleh'
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍34
Anonymous Quiz
5%
5
21%
"5true"
46%
6
27%
NaN
👍19❤1
Цепочка прототипов (prototype chain) — это механизм в JavaScript, с помощью которого объекты могут наследовать свойства и методы друг у друга. Этот механизм лежит в основе объектно-ориентированной модели JavaScript.
Каждый объект в JavaScript имеет свойство
__proto__
(или скрытое свойство [[Prototype]]
), которое указывает на его прототип. Прототип — это другой объект, от которого объект наследует свойства и методы. Объекты могут быть созданы с использованием конструктора, и все объекты, созданные одним и тем же конструктором, наследуют от одного и того же прототипа.Если свойство или метод не найдено у объекта, JavaScript будет искать его в прототипе объекта. Этот процесс продолжается вверх по цепочке прототипов до тех пор, пока не будет найдено свойство или не будет достигнут конец цепочки (обычно это
Object.prototype
). Если свойство не найдено в цепочке прототипов, результатом будет undefined
.Рассмотрим простой пример, чтобы проиллюстрировать, как работает цепочка прототипов: В этом примере
myDog
наследует метод speak
от Animal.prototype
и метод bark
от Dog.prototype
. Когда вызывается myDog.speak()
, JavaScript сначала ищет метод speak
в myDog
. Поскольку его там нет, он переходит к Dog.prototype
, где тоже его не находит, и затем переходит к Animal.prototype
, где метод speak
найден и выполняется.// Создаем объект Animal
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} издает звук.`);
};
// Создаем объект Dog, который наследует от Animal
function Dog(name, breed) {
Animal.call(this, name); // Вызов конструктора Animal
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype); // Наследование прототипа Animal
Dog.prototype.constructor = Dog; // Восстановление конструктора Dog
Dog.prototype.bark = function() {
console.log(`${this.name} лает.`);
};
const myDog = new Dog('Рекс', 'Лабрадор');
myDog.speak(); // Рекс издает звук.
myDog.bark(); // Рекс лает.
Все объекты, созданные с использованием литерала объекта
{}
, имеют в качестве прототипа Object.prototype
. Все функции, включая функции-конструкторы, имеют свойство prototype
, которое указывает на прототип объектов, созданных этой функцией.Animal.pro
. Методы, такие как toString()
, hasOwnProperty()
, isPrototypeOf()
, находятся в Object.prototype
и доступны всем объектам через цепочку прототипов.const obj = {};
console.log(obj.toString()); // [object Object]
console.log(obj.hasOwnProperty('toString')); // false, т.к. метод унаследован
Прототип объекта можно изменить с помощью метода
Object.setPrototypeOf()
, но это не рекомендуется из-за потенциальных проблем с производительностью.const cat = {
meow() {
console.log('Мяу!');
}
};
const myCat = Object.create(cat);
myCat.name = 'Мурка';
myCat.meow(); // Мурка мяукает.
Object.setPrototypeOf(myCat, {});
myCat.meow(); // Ошибка, так как метод больше не существует в цепочке прототипов
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26❤1
Anonymous Quiz
92%
Объект для отложенных и асинхронных вычислений
3%
Метод для обработки ошибок
2%
Способ создания нового объекта
2%
Синтаксис для объявления функции
❤9👍7😁3
Функция setTimeout используется для выполнения кода через определенное количество времени. Иногда возникает необходимость, чтобы
setTimeout
выполнялся позже или задержка была увеличена. Для этого можно изменить время задержки, переданное в качестве второго аргумента функции setTimeout
.// Выполнить функцию через 2 секунды (2000 миллисекунд)
setTimeout(() => {
console.log('Прошло 2 секунды');
}, 2000);
// Выполнить ту же функцию через 5 секунд (5000 миллисекунд)
setTimeout(() => {
console.log('Прошло 5 секунд');
}, 5000);
Если время задержки должно изменяться динамически в зависимости от определенных условий или переменных, вы можете использовать переменные для управления задержкой.
let delay = 3000; // Задержка в миллисекундах (3 секунды)
// Выполнить функцию через динамически заданное время
setTimeout(() => {
console.log(`Прошло ${delay / 1000} секунд`);
}, delay);
Иногда может потребоваться увеличивать задержку с течением времени или при выполнении определенных условий.
let delay = 1000; // Начальная задержка в миллисекундах (1 секунда)
let increment = 1000; // Увеличение задержки на 1 секунду
function delayedFunction() {
console.log(`Функция выполнена после ${delay / 1000} секунд`);
delay += increment; // Увеличить задержку
setTimeout(delayedFunction, delay); // Вызвать функцию с новой задержкой
}
// Начальный вызов функции
setTimeout(delayedFunction, delay);
Если нужно изменить задержку для уже запланированного вызова
setTimeout
, этого сделать нельзя напрямую. Однако, можно отменить текущий таймер и запланировать новый с новой задержкой.let timeoutId;
let delay = 2000; // Начальная задержка 2 секунды
function startTimeout() {
timeoutId = setTimeout(() => {
console.log('Таймер сработал');
}, delay);
}
function changeDelay(newDelay) {
clearTimeout(timeoutId); // Отменить текущий таймер
delay = newDelay; // Обновить задержку
startTimeout(); // Запланировать новый таймер с новой задержкой
}
// Запустить начальный таймер
startTimeout();
// Изменить задержку через 1 секунду
setTimeout(() => {
changeDelay(5000); // Изменить задержку на 5 секунд
}, 1000);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍34❤1🤯1
Anonymous Quiz
3%
String
2%
Number
6%
Boolean
89%
Object
👍11
Нужно вызвать этот метод через объект. Если метод не найден на самом объекте, интерпретатор JavaScript будет подниматься по цепочке прототипов до тех пор, пока не найдет метод или не достигнет вершины цепочки (обычно это
Object.prototype
).Рассмотрим пример с использованием функций-конструкторов и прототипов:
// Создаем конструктор Animal
function Animal(name) {
this.name = name;
}
// Добавляем метод speak к прототипу Animal
Animal.prototype.speak = function() {
console.log(`${this.name} издает звук.`);
};
// Создаем конструктор Dog, который наследует от Animal
function Dog(name, breed) {
Animal.call(this, name); // Вызов конструктора Animal
this.breed = breed;
}
// Наследуем прототип Animal
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// Добавляем метод bark к прототипу Dog
Dog.prototype.bark = function() {
console.log(`${this.name} лает.`);
};
// Создаем экземпляр Dog
const myDog = new Dog('Рекс', 'Лабрадор');
// Обращение к методам
myDog.speak(); // Рекс издает звук.
myDog.bark(); // Рекс лает.
Когда вы создаете новый экземпляр
Dog
, функция-конструктор Dog
вызывается, и у нового объекта myDog
появляются свойства name
и breed
.Объект
myDog
наследует методы speak
и bark
через цепочку прототипов.myDog.__proto__
указывает на Dog.prototype
.Dog.prototype.__proto__
указывает на Animal.prototype
. speak:
Когда вы вызываете
myDog.speak()
, интерпретатор сначала ищет метод speak
на объекте myDog
. Не найдя его там, он поднимается по цепочке прототипов и находит метод speak
в Animal.prototype
. bark:
Когда вы вызываете
myDog.bark()
, интерпретатор сначала ищет метод bark
на объекте myDog
. Не найдя его там, он поднимается по цепочке прототипов и находит метод bark
в Dog.prototype
.Если вы хотите проверить, где именно находится метод в цепочке прототипов, можно использовать метод
hasOwnProperty
для проверки собственного свойства объекта и оператор in
для проверки наличия свойства в объекте или его прототипах.console.log(myDog.hasOwnProperty('speak')); // false, так как метод унаследован
console.log('speak' in myDog); // true, так как метод найден в цепочке прототипов
console.log(myDog.hasOwnProperty('bark')); // false, так как метод унаследован
console.log('bark' in myDog); // true, так как метод найден в цепочке прототипов
Чтобы обратиться к методу в цепочке прототипов, достаточно вызвать метод через объект. Если метод не найден на самом объекте, JavaScript будет подниматься по цепочке прототипов до тех пор, пока не найдет метод или не достигнет вершины цепочки (обычно это
Object.prototype
).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2
Anonymous Quiz
62%
Object.assign()
13%
Object.copy()
21%
Object.clone()
4%
Object.merge()
👍11🤔5🤯1
Использует скрытое свойство
[[Prototype]]
(также известное как __proto__
) для каждого объекта, чтобы установить связь с его прототипом. Это позволяет объекту наследовать свойства и методы от другого объекта.Каждый объект в JavaScript имеет скрытое свойство
[[Prototype]]
, доступное как proto (неофициальный, но широко поддерживаемый способ доступа). Оно указывает на прототип объекта, от которого этот объект наследует свойства и методы. Это свойство устанавливается автоматически при создании объекта.Когда вы пытаетесь получить доступ к свойству или методу объекта, JavaScript сначала ищет его на самом объекте. Если свойство или метод не найдено, поиск продолжается в объекте, на который указывает proto. Этот процесс продолжается вверх по цепочке прототипов до тех пор, пока не будет найдено свойство или не будет достигнут конец цепочки (обычно это
Object.prototype
).Рассмотрим пример, чтобы проиллюстрировать, как работает цепочка прототипов:
// Создаем объект Animal
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} издает звук.`);
};
// Создаем объект Dog, который наследует от Animal
function Dog(name, breed) {
Animal.call(this, name); // Вызов конструктора Animal
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype); // Наследование прототипа Animal
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log(`${this.name} лает.`);
};
const myDog = new Dog('Рекс', 'Лабрадор');
myDog.speak(); // Рекс издает звук.
myDog.bark(); // Рекс лает.
Когда вы вызываете
myDog.speak()
, JavaScript сначала ищет метод speak
на самом объекте myDog
.Поскольку
myDog
не имеет собственного метода speak
, JavaScript смотрит на объект, на который указывает myDog.__proto__
. В данном случае это Dog.prototype
.Если метод
speak
не найден в Dog.prototype
, JavaScript продолжает искать в Dog.prototype.__proto__
, который указывает на Animal.prototype
.Метод
speak
найден в Animal.prototype
, и он вызывается.Если бы метод
speak
не был найден в Animal.prototype
, JavaScript продолжил бы поиск в Animal.prototype.__proto__
, который указывает на Object.prototype
. Если метод не найден и в Object.prototype
, возвращается undefined
.Операторвень поиска:
Проверяет, является ли объект экземпляром конструктора, следуя по цепочке прототипов.
console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Animal); // true
console.log(myDog instanceof Object); // true
Метод
isPrototypeOf:
Проверяет, находится ли объект в цепочке прототипов другого объекта.
console.log(Animal.prototype.isPrototypeOf(myDog)); // true
console.log(Dog.prototype.isPrototypeOf(myDog)); // true
Метод
Object.getPrototypeOf:
Возвращает прототип объекта.
console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🎉2❤1
Anonymous Quiz
15%
"33"
48%
9
27%
NaN
10%
"9"
🔥16👍9
Значение this зависит от контекста, в котором функция вызывается. Понимание того, как
this
определяется в различных ситуациях, является ключом к правильному использованию функций и методов в JavaScript. Рассмотрим основные правила и примеры.Глобальный контекст или контекст функции:
В глобальном контексте (вне любой функции) или внутри обычной функции (не метода объекта)
this
ссылается на глобальный объект, который является window
в браузере или global
в Node.js.console.log(this); // window в браузере или global в Node.js
function globalFunction() {
console.log(this); // window в браузере или global в Node.js
}
globalFunction();
Методы объекта:
Когда функция вызывается как метод объекта,
this
ссылается на объект, который использовался для вызова метода.const obj = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
obj.greet(); // 'Alice'
Конструкторы и классы:
this
ссылается на вновь созданный объект.function Person(name) {
this.name = name;
}
const person = new Person('Bob');
console.log(person.name); // 'Bob'
class Animal {
constructor(name) {
this.name = name;
}
}
const animal = new Animal('Charlie');
console.log(animal.name); // 'Charlie'
Явное задание
this
с помощью call
, apply
и bind
:Методы call и apply позволяют вызывать функцию с явно заданным значением this. Метод bind создает новую функцию, которая при вызове имеет определенное значение this.
function sayHello() {
console.log(this.name);
}
const person = { name: 'David' };
sayHello.call(person); // 'David'
sayHello.apply(person); // 'David'
const boundSayHello = sayHello.bind(person);
boundSayHello(); // 'David'
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25❤5
Anonymous Quiz
83%
document.createElement()
6%
document.newElement()
8%
document.addElement()
3%
document.createNode()
👍10🤔2