JS Flashcards
Что такое приведение или преобразование типов (type coercion)
Приведение (или преобразование) типов — это процесс преобразования значения из одного типа в другой.
В JavaScript преобразование типов может быть явным и неявным. Преобразование с помощью функции-конструктора является явным. Пример:const num = Number("123");
const boolValue = Boolean(0);
Так как JavaScript — это язык со слабой типизацией, значения в нем могут быть конвертированы между различными типами автоматически - это называется неявным преобразованием типов. Пример:if (value) {…};
const result = "3" * 2;
const comparison = 5 == "5";
Что такое apply?
apply()
- это метод встроенного объекта функции в JavaScript. Он позволяет вызвать функцию с заданным значением this
и аргументами, переданными в виде массива (или массивоподобного объекта).
function.apply(thisArg, [argsArray])
Пример использования apply():
function greeting(greet, punctuation) {
return ${greet}, ${this.name}${punctuation}
;
}
const person = {
name: ‘Alice’
console.log(greeting.apply(person, [‘Hello’, ‘!’]));
// Вывод: Hello, Alice!
Как отфильтровать массив?
Метод filter(), который позволяет отфильтровать элементы массива на основе заданного условия и создать новый массив с соответствующими элементами.
Формат метода filter():array.filter(callback(element[, index[, array]])[, thisArg])
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = numbers.filter((num) => {
return num % 2 === 0;
});
console.log(evenNumbers); // Выводит: [2, 4, 6, 8, 10]
Базовые операторы в JS
Операнд – то, к чему применяется оператор. Например, в умножении 5 * 2 есть два операнда: левый операнд равен 5, а правый операнд равен 2. Иногда их называют «аргументами» вместо «операндов».
Унарным называется оператор, который применяется к одному операнду. Например, оператор унарный минус “-“ меняет знак числа на противоположный
Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме.
Поддерживаются следующие математические операторы:
Сложение +,
Вычитание -,
Умножение *,
Деление /,
Взятие остатка от деления %,
Возведение в степень **.
Если бинарный оператор ‘+’ применить к строкам, то он их объединяет в одну - это называется конкатенация.
Унарным плюсом можно быстро привести операнд к числу.
Одной из наиболее частых числовых операций является увеличение или уменьшение на единицу.
Инкремент ++ увеличивает переменную на 1
Декремент – уменьшает переменную на 1
Операторы ++ и – могут быть расположены не только после, но и до переменной. Префиксная форма возвращает новое значение, в то время как постфиксная форма возвращает старое (до увеличения/уменьшения числа).
Когда оператор идёт после переменной — это «постфиксная форма»: counter++.
«Префиксная форма» — это когда оператор идёт перед переменной: ++counter.
Оператор «запятая» предоставляет нам возможность вычислять несколько выражений, разделяя их запятой ,. Каждое выражение выполняется, но возвращается результат только последнего.
Типы данных в JS
Есть восемь основных типов данных в JavaScript.
-
Числовой тип данных (number)
представляет как целочисленные значения, так и числа с плавающей точкой.
Кроме обычных чисел, существуют так называемые «специальные числовые значения», которые относятся к этому типу данных: Infinity, -Infinity (можем получить в результате деления на ноль) и NaN (NaN означает вычислительную ошибку. Это результат неправильной или неопределённой математической операции). -
BigInt
числовой примитив, который позволяет использовать большие числа с высокой точностью. Чтобы создать значение типа BigInt, необходимо добавить n в конец числового литерала: const bigInt = 1234567890123456789012345678901234567890n; -
Строка (string)
в JavaScript должна быть заключена в кавычки. Обратные кавычки имеют расширенную функциональность - позволяют нам встраивать выражения в строку, заключая их в ${…}. -
Булевый тип (boolean)
может принимать только два значения: true (истина) и false (ложь).
Такой тип, как правило, используется для хранения значений да/нет: true значит «да, правильно», а false значит «нет, не правильно». -
null
формирует отдельный тип, который содержит только значение null. Это специальное значение, которое представляет собой «ничего», «пусто» или «значение неизвестно». -
Специальное значение undefined
означает, что «значение не было присвоено». Если переменная объявлена, но ей не присвоено никакого значения, то её значением будет undefined. -
Symbol
примитивный тип данных, использующийся для создания уникальных идентификаторов. Даже если символы имеют одно и то же имя, это – разные символы. -
Тип object (объект)
не является примитивным типом данных. Объекты используются для хранения коллекций различных значений и более сложных сущностей. Объект может быть создан с помощью фигурных скобок {…} с необязательным списком свойств. Свойство – это пара «ключ: значение», где ключ – это строка (также называемая «именем свойства»), а значение может быть чем угодно.
Расскажи про тип данных число.
Тип данных “число” (number) в JavaScript представляет числовые значения. Также для этого типа данных существуют специальные значения Infinity, -Infinity и NaN (Not a Number).
В диапазоне от -2 в 53 степени до 2 в 53 степени, числа могут быть представлены точно.
Для типа данных “число” определены стандартные арифметические операции, такие как сложение (+), вычитание (-), умножение (*), деление (/), взятие остатка от целочисленного деления (%), возведение в степень (**), а также операции сравнения (>, <, >=, <=, ==, ===, !=, !==).
Числа также могут быть представлены в различных системах исчисления, таких как двоичная, восьмеричная или шестнадцатеричная системы. Чтобы перевести число в какую-то систему исчисления можно использовать метод toString:
let decimalNumber = 10;
let binaryNumber = decimalNumber.toString(2);
console.log(binaryNumber); // Выводит: 1010
Стандарт IEEE-754 определяет три специальных значения. Эти значения принадлежат типу number, но не работают, как обычные числа:
- бесконечность Infinity;
- минус бесконечность -Infinity;
- не число (not a number) NaN.
Значение NaN используется, чтобы сообщить об операции, результатом которой оказалось не число. В JavaScript существует пять операций, которые могут вернуть NaN:
1. ошибка парсинга числа (например, при попытке превратить строку в число parseInt('привет'))
.
2. результат математической операции не находится в полей действительных чисел (например, взятие корня от -1).
3. один из операндов в арифметической операции — NaN (5 + NaN)
4. результат арифметической операции не определён для переданных операндов undefined + undefined
.
5. арифметическая операция со строкой, кроме сложения 'привет' * 5
Согласно спецификации, NaN не равен самому себе. Для проверки на NaN пользуйтесь функцией Number.isNaN()
, которая возвращает true если переданное значение — NaNNumber.isFinite()
проверяет и на Infinity, и на Nan - на них возвращается false.
Для округления, взятия корней и других математических операций в JavaScript существует отдельный модуль Math.round()
— округление по обычным правилам;floor()
— округление вниз;ceil()
— округление вверх;trunc()
— отбрасывание дробной части, не обращая внимания на знак аргумента.
Сам по себе примитивный тип «число» не имеет методов. Когда происходит вызов метода у числа, оно автоматически оборачивается в специальную обёртку Number, которая и содержит методы:
- проверки на специальные значения isNaN(), isFinite().
- toString(2) переводит в строку с определенной системой исчисления
- toFixed() форматирует число, обрезая значения после запятой. Возвращает строку, а не число.
Если после округления нужно производить другие арифметические операции, то лучше распарсить число с помощью parseFloat().
Тип данных BigInt
Тип большого целого BigInt — примитивный тип, который представляет целые числа больше 2 в степени 53 - 1. Эти числа уже не помещаются в стандартный примитив «число».
Создать BigInt можно двумя способами.
1️⃣ Добавить суффикс n в конец записи числа:
const biggy = 9997000254740991n
2️⃣ Вызвать конструктор BigInt:
const alsoBig = BigInt(9997000254999999)
Тип данных строка
Строки представляют собой последовательность символов. Созданная строка является иммутабельной (immutable) и не может быть изменена.
Есть несколько способов создать строку:
- одинарными кавычками ‘;
- двойными кавычками “;
- шаблонной строкой через обратный апостроф ` - бэктик.
Если в записи одинарными кавычками нужно поставить апостроф, то символ экранируют обратным слэшем . Так мы даём JavaScript понять, что это просто символ, а не закрывающая кавычка.
Строки можно сравнивать между собой, для сравнения используется лексикографический порядок. Это означает, что первые символы алфавита считаются меньше последних.
Алгоритм посимвольно сравнивает строки до первого несовпадения, либо пока не закончится одна из строк.
console.log(‘А’ < ‘Я’) // true
console.log(‘Кот’ > ‘Код’) // true
console.log(‘Код’ < ‘Кодер’) // true
console.log(‘Код’ === ‘Код’) // true
Сравнение учитывает регистр букв, если необходимо регистронезависимое сравнение, то обе строки приводятся к верхнему или нижнему регистру с помощью методов toUpperCase или toLowerCase.
Сам по себе примитивный тип «строка» не имеет методов. Когда происходит вызов метода, оно автоматически оборачивается в специальную обёртку, которая и содержит методы.
length: Возвращает длину строки.
toUpperCase(): Возвращает новую строку, содержащую все символы исходной строки в верхнем регистре.
toLowerCase(): Возвращает новую строку, содержащую все символы исходной строки в нижнем регистре.
substring(startIndex, endIndex): Возвращает подстроку, которая начинается со значения индекса startIndex
до значения индекса endIndex
(не включительно).const str = "Hello, world!";
console.log(str.substring(0, 5)); // Вывод: "Hello"
indexOf(substring): Возвращает индекс первого вхождения подстроки substring
в строке. Если подстрока не найдена, возвращает -1
.
replace(oldSubstring, newSubstring): Заменяет первое вхождение подстроки oldSubstring
на подстроку newSubstring
и возвращает новую строку.
const str = “Hello, world!”;
console.log(str.replace(“world”, “JavaScript”)); // Вывод: “Hello, JavaScript!”
**split(separator)**: Разбивает строку на массив подстрок с использованием указанного разделителя
separator`.
trim(): Удаляет пробельные символы с начала и конца строки и возвращает новую строку.
Тип данных Boolean
Логический или булев тип boolean может принимать лишь истинное (true) и ложное (false) значения. Значения этого типа используются в условных выражениях.
Создать булевое значение можно несколькими способами.
- явно указать значение, используя ключевые слова true и false:
const truthyValue = true // «Истина»
- использовать метод Boolean:
const falsyValue = Boolean(‘’) // «Ложь»
- использовать выражения, значениями которых будут «истина» или «ложь».
const anotherTruthy = 4 < 5
- Если вызвать одинарное ! или двойное отрицание !!, можно быстро привести любое выражение к логическому типу.
Обычно логическим переменным дают названия, начинающиеся с английских глаголов is, should, does, can и подобных.
Тип данных Undefined
**Undefined — это примитивный тип данных, состоящий из одного значения undefined. Оно используется, чтобы обозначить неопределённое значение. **
- JavaScript автоматически устанавливает значение undefined объявленным переменным, которые не были проинициализированы значением.
- JavaScript автоматически устанавливает значение undefined в аргумент функции, если значение не передали при вызовеhello('Витя') // Привет, Витя
hello() // Привет, undefined
Вручную установленное undefined используют, чтобы обозначить неизвестное значение:const person = {
name: 'Пётр',
lastName: 'Романов',
age: undefined
}
Тип данных Null
Null — это примитивный тип данных, который состоит из единственного значения null. Значение null используют, когда нужно обозначить намеренное отсутствие значения.
null обозначает понятия «отсутствует», «ничего», «пусто» или «значение неизвестно». Оно всегда явно задаётся программистом, JavaScript автоматически не устанавливает его.
В JavaScript null используется только для обозначения конца цепочки прототипов, чтобы показать, что следующий прототип отсутствует.
В языке существует похожий примитив undefined, он обозначает, что значение ещё не установлено. Их можно легко спутать, потому что оба обозначают отсутствие значения. Разница состоит в том, что null обозначает намеренное отсутствие, а undefined — неявное.
Тип данных Symbol
Символ (Symbol) — примитивный тип, значения которого создаются с помощью вызова функции Symbol. Каждый созданный символ уникален. Символы могут использоваться в качестве имён свойств в объектах. Символьные свойства могут быть прочитаны только при прямом обращении и не видны при
обычных операциях.
Для создания символа нужно вызвать функцию Symbol:const sym = Symbol()
const symTwo = Symbol()
console.log(sym === symTwo)
// false
Символы используются для создания скрытых свойств объектов. В отличие от свойств, ключом которых является строка, символьные свойства может читать только владелец символа. Скрытые свойства не видны при его обходе с помощью for…in. Это может пригодиться, когда необходимо добавить свойства объекту, который могут модифицировать другие части программы. Таким образом только вы сможете читать созданное свойство, а гарантия уникальности символов гарантирует и отсутствие конфликтов имён.
Созданный символ уникален, но как быть, если он нужен в нескольких местах программы? Для решения этой проблемы существует глобальный реестр символов, он хранит символы по строковым ключам. При обращении по ключу всегда будет возвращаться один и тот же символ.
Работа с реестром символов организована с помощью двух методов:
- Symbol.for(ключ)
— возвращает символ, хранящийся по ключу. Если символа ещё не существует, он создаётся автоматически.
- Symbol.keyFor(символ)
— возвращает строковый ключ, который хранит переданный символ или undefined, если символ не
хранится в реестре.
Что такое массив?
**Массив - упорядоченная коллекция данных, в которой присутствуют 1-й, 2-й, 3-й элементы и т.д. Например, она понадобится нам для хранения списка чего-либо:
пользователей, товаров, элементов HTML и т.д. Массив – это особый подвид объектов.*
let arr = new Array();
let arr = [];
В массиве могут храниться элементы любого типа. Элементы нумеруются и хранятся в том порядке, в котором их поместили в массив. Элементы массива нумеруются, начиная с нуля. Мы можем получить элемент, указав его номер в квадратных скобках.
Получение последних элементов массива:fruits[fruits.length - 1]
fruits.at (-1)
Методы:slice
: Создает новый массив, содержащий копию части исходного массива. Можно указать начальный и конечный индексы для выбора нужной части массива.const arr = [1, 2, 3, 4, 5];
const slicedArr = arr.slice(1, 4);
console.log(slicedArr); // Вывод: [2, 3, 4]
splice
: Изменяет содержимое массива, удаляя, заменяя или добавляя элементы на указанной позиции.const arr = [1, 2, 3, 4, 5];
arr.splice(2, 2, 'a', 'b'); // индекс, с которого начинается изменение массива, количество элементов, которые нужно удалить из массива, элементы, которые нужно добавить в массив на место удаленных элементов
console.log(arr); // Вывод: [1, 2, 'a', 'b', 5]
push
добавляет элемент в конец.pop
удаляет последний элемент.unshift
добавляет элемент в начало массива:shift
удаляет элемент в начале, сдвигая очередь, так что второй элемент становится первым.
Методы push и unshift могут добавлять сразу несколько элементов. Методы push/pop выполняются быстро, а методы shift/unshift – медленно, потому что работать с концом массива всегда быстрее, чем с началом.
Используйте indexOf()
, чтобы найти, под каким индексом хранится элемент.
Используйте includes()
, чтобы проверить, что элемент есть в массивеconcat
: Объединяет два или более массивов и возвращает новый массив, содержащий элементы из всех объединенных массивов.forEach
: Выполняет указанную функцию один раз для каждого элемента массива. map
: Создает новый массив, содержащий результаты вызова указанной функции для каждого элемента исходного массива.
Многомерные массивы
Массивы могут содержать элементы, которые тоже являются массивами. Это можно использовать для создания многомерных массивов, например, для хранения матриц:let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
alert( matrix[1][1] ); // 5, центральный элемент
В современном JavaScript очень популярна деструктуризация массивов. Этот подход позволяет создавать переменные из элементов массива в одну строку:const catProfile = [
'Maru',
'Scottish Fold',
true,
'https://youtu.be/ChignoxJHXc'
]
const [name, breed] = catProfile
console.log(name) // Maru
Тип данных Object
Объект (object) — это особый тип данных, он единственный не является примитивом в JS.
Каждое свойство состоит из ключа и значения. Ключ может быть строкой или символом, а значение может быть любым.
Чаще всего объекты создают с помощью литеральной записи.const cat = {}
Создать объект также можно с помощью конструктора Object. Это объектно-ориентированный стиль программирования:const book = new Object({ title: 'Война и мир', author: 'Лев Толстой' })
Чтение свойств с помощью точки:console.log(
На полке стоит «${book.title}»)
// На полке стоит «Война и мир»
Альтернативно для чтения можно использовать квадратные скобки:console.log(
На полке стоит «${book[‘title’]}»)
Для добавления и изменения свойств используется одинаковый синтаксис. Нужно обратиться к свойству и присвоить в него значение с помощью стандартного оператора присваивания =.
Если свойство не существует, оно будет создано:const book = {
title: 'Капитанская дочка'
}
book.author = 'А.С.Пушкин' // добавляем новое свойство
book.title = 'Сказка о царе Салтане' // изменяем существующее
console.log(book) // { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
delete book['author']
delete book.title
Чаще всего свойства не удаляют, а сбрасывают значение, устанавливая undefined или подходящее по смыслу:book.title = undefined
book['author'] = undefined
Для проверки, есть ли свойство у объекта, используйте оператор in:const user = {
firstName: 'Марина',
username: 'zloyDuh'
}
console.log('firstName' in user)
// true
console.log('age' in user)
// false
Преобразование в массив:
Object.keys(user) = [“name”, “age”]
Object.values(user) = [“John”, 30]
Object.entries(user) = [ [“name”,”John”], [“age”,30] ]
Преобразование обратно в объект:
Object.fromEntries
Методы объектов
Статические методы объекта - методы, которые предварительно определены и вызываются в классе объектов.Object.keys(obj)
– возвращает массив ключей.Object.values(obj)
– возвращает массив значений.Object.entries(obj)
– возвращает массив пар [ключ, значение].
Обойти их
for (let value of Object.values(user)) {
alert(value); // John, затем 30
}
Object.fromEntries(array)
- преобразует массив в объект
// преобразовать в массив, затем map, затем fromEntries обратно объект
Object.fromEntries( Object.entries(prices).map(([key, value]) => [key, value * 2]) );
Методы экземпляра — это методы, встроенные в объекты, которые работают с конкретным экземпляром объекта, а не с классом объекта.Object.prototype.hasOwnProperty()
возвращает логическое значение, указывающее, имеет ли объект указанное свойство.
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty(‘property1’));
// Expected output: true
Метод Object.create()
создаёт новый объект с указанным прототипом и свойствами.
Метод Object.assign()
используется для копирования перечисляемых и собственных свойств из одного или более исходных объектов в целевой объект. После копирования он возвращает целевой объект.
var o1 = { a: 1 };
var o2 = { [Symbol(‘foo’)]: 2 };
var obj = Object.assign({}, o1, o2);
console.log(obj); // { a: 1, [Symbol(“foo”)]: 2 }
Object.preventExtensions(объект)
предотвращает добавление новых свойств к объекту (то есть, предотвращает расширение этого объекта в будущем).Object.isExtensible(объект)
определяет, является ли объект расширяемым (то есть, можно ли к нему добавлять новые свойства).
Метод Object.freeze()
предотвращает модификацию свойств и значений объекта и добавление или удаление свойств объекта.
Метод Object.isFrozen()
позволяет определить, был ли объект заморожен или нет, и возвращает логическое значение.
Метод Object.seal()
предотвращает добавление новых свойств объекта, но позволяет изменять существующие свойства.
// Возвращает true, если объект “запечатан” Object.isSealed(объект)
определяет, является ли объект запечатанным.
Метод Object.getPrototypeOf()
используется для получения внутреннего скрытого [[Prototype]] объекта, также доступного через свойство __proto__.
Существует также связанный с ним метод Object.setPrototypeOf()
, который добавляет один прототип к другому объекту. Но вместо этого рекомендуется использовать Object.create()
, поскольку он быстрее и эффективнее.
Метод Object.defineProperty()
определяет новое или изменяет существующее свойство непосредственно на объекте, возвращая этот объект.
// Добавить или изменить свойство объекта
Object.defineProperty(объект, свойство, описатель)
Object.defineProperty(объект, свойство, {value : значение})
Object.defineProperty(person, “language”, {writable:false}); // делаем свойство language только для чтения
// Добавить или изменить несколько свойств объекта Object.defineProperties(объект, описатель)
- writable : true // Значение свойства можно изменять
- enumerable : true // Свойство может перечисляться
- configurable : true // Свойство может настраиваться
// Определение геттера
get: function() {
return language
}
// Определение сеттера
set: function(value) {
language = value
}
Полифил map
// Добавляем новый метод myMap в прототип массива
Array.prototype.myMap = function(callback) {
// Проверяем, что this является массивом или строкой
// Если тип неверный, выбрасываем ошибку TypeError
if (!this instanceof Array || !this instanceof String) {
throw new TypeError(‘Wrong type’);
}
// Проверяем, что callback является функцией
// Если не является, выбрасываем ошибку TypeError
if (typeof callback !== “function”) {
throw new TypeError(‘Callback isn't function’);
}
const result = [];
// Проходим по каждому элементу исходного массива/строки
// Вызываем callback для каждого элемента и добавляем результат в новый массив
for (let i = 0; i < this.length; i += 1) {
result.push(callback(this[i], i, this));
}
return result;
};
Полифил reduce
Метод reduce применяет функцию reducer к каждому элементу массива (слева-направо), возвращая одно результирующее значение.
Пример reduce:
let people = [
{ name: “Ira”, age: 10 },
{ name: “Kira”, age: 20 },
{ name: “Lira”, age: 30 },
{ name: “Vira”, age: 40 },
];
const amount = people.reduce((total, elem) => (total += elem.age), 0); //100
Полифил reduce:
// Добавляем новый метод myReduce в прототип массива
Array.prototype.myReduce = function(callback, accumulator) {
// Проверяем, что this является массивом или строкой
// Если тип неверный, выбрасываем ошибку TypeError
if (!this instanceof Array || !this instanceof String) {
throw new TypeError(‘Wrong type’);
}
// Проверяем, что callback является функцией
// Если не является, выбрасываем ошибку TypeError
if (typeof callback !== “function”) {
throw new TypeError(‘Callback isn't function’);
}
// Инициализируем аккумулятор значением, переданным в качестве аргумента или первым элементом массива
// Устанавливаем начальное значение индекса в зависимости от наличия аргумента аккумулятора
let acc = arguments.length > 1 ? accumulator : this[0];
let iStart = arguments.length > 1 ? 0 : 1;
// Проходим по каждому элементу массива/строки, начиная с определенного индекса
// Вызываем callback с текущим значением аккумулятора, текущим элементом, индексом и самим массивом
for (let i = iStart; i < this.length; i += 1) {
acc = callback(acc, this[i], i, this);
}
return acc;
};
let arr = [0, 1, 3, 5, 7, 8];
const myReduceResult = arr.myReduce((acc, curr, idx, arr) => {
// Используем myReduce для расчета суммы элементов массива
acc += curr;
return acc;
});
console.log(myReduceResult);
// Вывод: 24
Что такое Big-О
В программировании Big-О показывает эффективность конкретного алгоритма. Всегда рассматривается наихудший вариант расчета. Конcтанты откидываются.
Одними из самых часто встречаемых сложностей являются:
- О(1) - самый эффективный. Вывод 10 элемента в массиве, т.к. это делается по индексу, нам не важно 100 там элементов или миллион, на задачу требуется всегда один шаг. Также хэш-таблицы имеют эту сложность для поиска, индексации и добавления.
- O(log n) - поиск в отсортированном массиве через бинарный поиск. Сюда относятся все функции, где входящий массив или структура данных делится пополам для поиска.
- O(n) - поиск элемента в несортированном массиве - для получения результата, вам придется перебрать весь список. Или суммирование элементов массива - тоже нужно пройти все элементы. Чем больше массив, тем больше операций. Можно сказать «сложность порядка n (order n)». Так же такой тип алгоритмов называют «линейными» или что алгоритм «линейно масштабируется». Интересно: Если мы знаем, что массив начинается с 1, отсортирован и не имеет пропусков, для суммирования можно применить формулу S = n(n+1)/2 (где n последний элемент массива) - такая запись будет уже более эффективной O(1).
- O(n log n) - n раз logn. Как пример сортировка слиянием. Получается O(n * log n), или O(n log n).
- O(n²) - пузырьковая сортировка, поиск дублей в цикле, который в другом цикле. Массив из 4 элементов требует 16 шагов, массив из 10 элементов – 100 шагов.
- O(2^n) - поиск всех подмножеств массива. Каждый элемент множества может быть либо включен, либо исключен из подмножества. Набор из четырех элементов [A,B,C,D, E] будет иметь 2^5 или 32 подмножеств.
[A], [B], [C], [D], [E]
[A,B], [A,C], [A,D], [A, E], [B,C], [B,D], [C,D] и т.д. - O(n!) - самый неэффективный. К примеру, поиск всех возможных вариантов расположения элементов в массиве [A, B, C, D] потребует 4! или 24 шага.
Что такое bind, когда он используется, полифил bind
Метод bind()
является одним из методов встроенного объекта функции в JavaScript. Он используется для создания новой функции, привязанной к определенному контексту выполнения. Это позволяет явно указать значение this
внутри функции и также позволяет привязать предопределенные аргументы.
Привязанная функция, созданная с помощью bind()
, не вызывается немедленно. Вместо этого, она возвращается, чтобы ее можно было вызвать позднее.
bind()
принимает один или более аргументов:
- thisArg: Объект, который будет использоваться в качестве значения this
внутри функции, которая будет создана при вызове bind()
.
- аргументы: Предопределенные аргументы, которые будут переданы в функцию при вызове.
Пример использования bind()
:const obj = {
x: 42,
getY: function() {
return this.x;
}
};
const boundGetY = obj.getY.bind(obj); // Создаем новую функцию, в которой this будет ссылаться на объект obj
console.log(boundGetY()); // Вывод: 42
const anotherObj = {
x: 99
};
const boundGetY2 = obj.getY.bind(anotherObj);
console.log(boundGetY2()); // Вывод: 99
Function.prototype.myBind = function (...args) {
var callback = this,
ctx = args.splice(1);
return function (...a) { //параметр …a содержит все аргументы, которые можно передать result2()методу.
callback.call(args[0], ...[...ctx, ...a]);
// args[0] является первым аргументом, переданным myBind()методу (то есть объекту myName),
// ctx содержит все остальные аргументы, переданные нашему myBind()методу
};
};
const result2 = printName.myBind(myName, "Palia");
result2("India");
Что такое call, когда он используется, полифил call
call()
- это метод встроенного объекта функции в JavaScript. Он используется для вызова функции, устанавливая указанное значение this
и передавая аргументы в виде списка. При использовании call()
, функция вызывается с установленным значением this
, которое передается в thisArg
, и аргументами, которые передаются в списке после thisArg
.
Синтаксис метода call()
:function.call(thisArg, arg1, arg2, ...)
-
thisArg
: Объект, который будет использоваться в качестве значенияthis
внутри функции. -
arg1
,arg2
, …: Аргументы, которые будут переданы в функцию при вызове.
Пример использования call()
:const person1 = {
name: 'Alice',
greeting: function() {
return 'Hello, ' + this.name + '!';
}
};
const person2 = {
name: 'Bob'
};
console.log(person1.greeting.call(person2)); // Output: Hello, Bob!
Полифил:Function.prototype.myCall = function (context, ...args) {
let currentContext = context || globalThis;
let randomProp = Math.random();
while (currentContext[randomProp] !== undefined) {
randomProp = Math.random();
} // генерируем случайное свойство, используя Math.random,чтобы убедиться, что свойство уникально.
currentContext[randomProp] = this;
let result = currentContext[randomProp](...args);
delete currentContext[randomProp];
return result;
};
printName.myCall(myName, "Palia", "India");
Объект Date
Объект JavaScript Date — это глобальный объект, который используется для работы с датами и временем. Объекты Date основаны на значении времени, которое представляет собой количество миллисекунд с 1 января 1970 года по всемирному координированному времени.
Важно: при установке месяца, отчёт идёт с 0, где 0 — это январь. При выводе дня недели возвращаемое значение также начинается с 0 и означает воскресенье.
Основные методыnew Date()
создаёт экземпляр Date с текущей датой и временем.new Date(значение)
создаёт Date с переданным значением времени. Значение должно быть в формате, который распознается методом Date.parse()
, то есть быть совместимым с IETF RFC 2822 или с ISO8601.new Date(год, месяц, день, часы, минуты, секунды, миллисекунды)
создаёт класс Date в местной часовой зоне. Год и месяц являются обязательными параметрами. Остальные параметры, начиная с часов, будут по умолчанию равны 0, а день — 1.new Date(миллисекунды)
создаёт Date со временем в миллисекундах. Количество миллисекунд измеряется с 1 января 1970 года UTC.getFullYear()
— возвращает год;getMonth()
— возвращает месяц с 0 до 11;getDate()
— возвращает день месяца с 1 до 31;getDay()
— возвращает порядковый номер дня недели с 0 до 6;getHours()
— возвращает часы с 0 до 23;getMinutes()
- возвращает минуты от 0 до 59;getSeconds()
- возвращает секунды от 0 до 59;getMilliseconds()
- возвращает миллисекунды от 0 до 999.getTime()
возвращает значение в миллисекундах, прошедших с 1 января 1970 года, соответствующее указанной дате по UTC.getTimezoneOffset()
возвращает смещение в минутах между текущей часовой зоной и UTC.setFullYear(год, месяц, день)
устанавливает год, значения месяца и дня необязательны.setMonth(месяц, день)
устанавливает месяц, передавать день необязательно.setDate(день)
устанавливает день месяца.setHours(часы, минуты, секунды, миллисекунды)
устанавливает часы. Значения минут, секунд, миллисекунд необязательны.setMinutes(минуты, секунды, миллисекунды)
- устанавливает минуты. Секунды и миллисекунды необязательны.setSeconds(секунды, миллисекунды)
устанавливает секунды. Миллисекунды передавать необязательно.
setMilliseconds(миллисекунды) - устанавливает миллисекунды.
Для UTC аналогичные методы, только добавляем UTC после set. Например, setUTCMilliseconds(миллисекунды)
.
И метод, который относится только к UTC:setTime(значение)
устанавливает значение, которое равно количеству миллисекунд, прошедших с 1 января 1970 года.
Метод Date.parse(значение)
используется для разбора (ещё говорят парсинга) строкового представления даты.
Возвращает значение, равное количеству миллисекунд, прошедших с 1 января 1970 года.
Для отображения Date в различных форматах существует метод toLocaleDateString(локаль, опции)
.
Локаль — это необязательный параметр, который является строкой или массивом строк с языковой меткой BCP 47.
Например, en-US или de-DE. Локаль хранит региональные настройки о формате дат, номеров, адресов.
Опции — необязательный параметр с объектом настроек. Доступные свойства:
localeMatcher — алгоритм поиска локали, используется для выбора подходящей локали. Принимает значения lookup или best fit. По умолчанию best fit.
timeZone — значение используемого часовой зоны. Все браузеры должны принимать значение UTC, значение по умолчанию равно значению часовой зоны среды выполнения. Формат принимаемого значения может различаться в различных браузерах.
hour12 — значение, которое определяет, использовать ли 12-часовой формат вывода. Принимает true или false.
formatMatcher — алгоритм поиска формата, используется для выбора формата отображения. Принимает значения basic или best fit. По умолчанию best fit.
timeZoneName — формат названия часовой зоны. Принимает long или short.
weekday — значение дня недели. Принимает narrow, short и long.
era — значение эры. Принимает narrow, short и long.
year — значение года. Принимает numeric и 2-digit.
month — значения месяца. Принимает numeric, 2-digit, narrow, short и long.
day — значения дня. Принимает numeric и 2-digit.
hour — значения часа. Принимает numeric и 2-digit.
minute — значения минут. Принимает numeric и 2-digit.
second — значения секунд. Принимает numeric и 2-digit.
Браузеры обязаны поддерживать следующие наборы настроек отображения:weekday, year, month, day, hour, minute, second
weekday, year, month, day
year, month, day
year, month
month, day
hour, minute, second
hour, minute
Date.now()
— метод, который возвращает текущее время в миллисекундах, прошедших с 1 января 1970 года UTC.
Если вам не хватает функциональности, представленной классом Date, например, недостаточно его возможностей форматирования или парсинга, то можно посмотреть в сторону библиотек day.js или date-fns.
В следующей таблице перечислены стандартные свойства объекта Date.
prototype
- Позволяет добавлять новые свойства и методы к объекту Date.
Примечание. У каждого объекта в JavaScript есть свойство конструктора, которое ссылается на функцию конструктора, которая использовалась для создания экземпляра этого объекта.
В следующей таблице перечислены стандартные методы объекта Date.
- getDate()
: Возвращает день месяца (от 1 до 31).
- getDay()
: Возвращает день недели (от 0 до 6).
- getFullYear()
: Возвращает год (четыре цифры).
- getHours()
: Возвращает час (от 0 до 23).
- getMilliseconds()
: Возвращает миллисекунды (от 0 до 999).
- getMinutes()
: Возвращает минуты (от 0 до 59).
- getMonth()
: Возвращает месяц (от 0 до 11).
- getSeconds()
: Возвращает секунды (от 0 до 59).
- getTime()
: Возвращает количество миллисекунд, прошедших с полуночи 1 января 1970 года.
- getTimezoneOffset()
: Возвращает разницу во времени между временем UTC и местным временем в минутах.
- getUTCDate()
: Возвращает день месяца по всемирному времени (от 1 до 31).
- getUTCDay()
: Возвращает день недели по всемирному времени (от 0 до 6).
- getUTCFullYear()
: Возвращает год по всемирному времени.
- getUTCHours()
: Возвращает час по всемирному времени (от 0 до 23).
- getUTCMilliseconds()
: Возвращает миллисекунды по всемирному времени (от 0 до 999).
- getUTCMinutes()
: Возвращает минуты по всемирному времени (от 0 до 59).
- getUTCMonth()
: Возвращает месяц по всемирному времени (от 0 до 11).
- getUTCSeconds()
: Возвращает секунды по всемирному времени (от 0 до 59).
-
now()
- Возвращает количество миллисекунд, прошедших с полуночи 1 января 1970 года. -
parse()
- Разбирает строку даты и возвращает количество миллисекунд с 1 января 1970 года. -
setDate()
- Устанавливает день месяца объекта даты. -
setFullYear()
- Устанавливает полный год объекта даты. -
setHours()
- Устанавливает часы объекта даты. -
setMilliseconds()
- Устанавливает миллисекунды объекта даты. -
setMinutes()
- Устанавливает минуты объекта даты. -
setMonth()
- Устанавливает месяц объекта даты. -
setSeconds()
- Устанавливает секунды объекта даты. -
setTime()
- Устанавливает дату на указанное количество миллисекунд после/до 1 января 1970 года. -
setUTCDate()
- Устанавливает день месяца объекта даты по всемирному времени -
setUTCFullYear()
- Устанавливает год объекта даты по всемирному времени. -
setUTCHours()
- Устанавливает часы объекта даты по всемирному времени. -
setUTCMilliseconds()
- Устанавливает миллисекунды объекта даты по всемирному времени. -
setUTCMinutes()
- Установите минуты объекта даты по всемирному времени. -
setUTCMonth()
- Устанавливает месяц объекта даты по всемирному времени. -
setUTCSeconds()
- Установите секунды объекта даты по всемирному времени. -
toDateString()
- Преобразует часть даты объекта Date в удобочитаемую форму. -
toISOString()
: Возвращает дату в виде строки, отформатированной в соответствии со стандартом ISO. -
toJSON()
: Возвращает дату в виде строки в формате даты JSON. -
toLocaleDateString()
: Возвращает часть даты объекта Date в виде строки локального формата. -
toLocaleTimeString()
: Возвращает временную часть объекта Date в виде строки локального формата. -
toLocaleString()
: Преобразует объект Date в строку локального формата. -
toString()
: Преобразует объект Date в строку. -
toTimeString()
: Преобразует временную часть объекта Date в строку. -
toUTCString()
: Преобразует объект Date в строку по всемирному времени. -
UTC()
: Возвращает количество миллисекунд в объекте Date с 00:00:00 (полночь) 1 января 1970 года по всемирному времени. -
valueOf()
: Возвращает примитивное значение объекта Date.
Что такое DOM Events?
Событие – это сигнал от браузера о том, что что-то произошло. Все DOM-узлы подают такие сигналы (хотя события бывают и не только в DOM).
События мыши:
- click
– происходит, когда кликнули на элемент левой кнопкой мыши (на устройствах с сенсорными экранами оно происходит при касании).
- contextmenu
– происходит, когда кликнули на элемент правой кнопкой мыши.
- mouseover
/ mouseout
– когда мышь наводится на / покидает элемент.
- mousedown
/ mouseup
– когда нажали / отжали кнопку мыши на элементе.
- mousemove
– при движении мыши.
События на элементах управления:
- submit
– пользователь отправил форму <form>.
- focus
– пользователь фокусируется на элементе, например нажимает на <input></input>.
Клавиатурные события:
- keydown и keyup
– когда пользователь нажимает / отпускает клавишу.
События документа:
- DOMContentLoaded
– когда HTML загружен и обработан, DOM документа полностью построен и доступен.
CSS events:
- transitionend
– когда CSS-анимация завершена.
Существует множество других событий.
Событию можно назначить обработчик, то есть функцию, которая сработает, как только событие произошло.
Именно благодаря обработчикам JavaScript-код может реагировать на действия пользователя.
1. Обработчик может быть назначен прямо в разметке, в атрибуте, который называется on<событие>
. <input value="Нажми меня" onclick="alert('Клик!')" type="button"
2. Можно назначать обработчик в JS, используя свойство DOM-элемента on<событие>
. elem.onclick = function() { alert('Спасибо'); };
Так как у элемента DOM может быть только одно
свойство с именем onclick, то назначить более одного обработчика так нельзя.
3. И последний и более гибкий способ: addEventListener
и removeEventListener
. С помощью него можно повесить более одного обработчика на одно событие, а также можно удалить обработчик, вызвав его и передав ту же функцию. Есть несколько типов событий, которые работают только через него, к примеру transitionend и DOMContentLoaded. Также addEventListener
поддерживает объекты в качестве обработчиков событий. В этом случае вызывается метод объекта handleEvent.
Не важно, как вы назначаете обработчик – он получает объект события первым аргументом. Этот объект содержит подробности о том, что произошло.
Расскажи про Form и Input Events
Form и Input Events - это события, которые позволяют отслеживать и реагировать на действия пользователя, связанные с отправкой формы, изменением значений полей ввода и другими взаимодействиями с элементами форм и ввода.
Некоторые из наиболее часто используемых событий форм и ввода включают:
-
submit
: Событиеsubmit
возникает, когда пользователь отправляет форму. Это может произойти, например, при нажатии на кнопку отправки или использовании клавиши Enter в текстовом поле. Для отслеживания отправки формы вы можете прослушивать событиеsubmit
на элементе. -
input
: Событиеinput
возникает, когда значение в поле ввода изменяется пользователем. Это может быть поле ввода текста, чекбокс, переключатель и другие элементы. Событиеinput
позволяет реагировать на моментальные изменения значения в поле ввода. -
change
: Событиеchange
возникает, когда значение в поле ввода изменяется и пользователь уводит фокус с элемента. Это позволяет отслеживать изменения значения и принимать соответствующие действия, когда пользователь закончил ввод. -
cut
: Событиеcut
возникает, когда пользователь вырезает выделенный текст или другой выделенный контент с использованием горячих клавиш или контекстного меню. Вы можете использовать это событие для выполнения дополнительных действий при вырезании данных пользователем. Это событие можно предотвратить, чтобы запретить вырезание содержимого. -
copy
: Событиеcopy
возникает, когда пользователь копирует выделенный текст или другой выделенный контент с использованием горячих клавиш или контекстного меню. Подобно событиюcut
, вы можете использовать эту возможность для выполнения дополнительных действий при копировании данных пользователем. Можно предотвратить это действие, чтобы запретить копирование содержимого. -
paste
: Событиеpaste
возникает, когда пользователь вставляет данные из буфера обмена в поле ввода или другой элемент на странице. Вы можете использовать это событие для выполнения дополнительной обработки данных, вставленных пользователем. Можно предотвратить вставку данных, чтобы запретить вставку содержимого. -
focus
: Событиеfocus
возникает, когда элемент ввода или другой элемент получает фокус. Например, когда пользователь щелкает на текстовое поле. -
blur
: Событиеblur
возникает, когда элемент ввода или другой элемент теряет фокус. Например, когда пользователь переключается на другой элемент или щелкает вне текстового поля. -
select
: Событиеselect
возникает, когда пользователь выбирает (выделяет) текст в элементе ввода или другом элементе на странице.
Как перебрать ключи и значения объекта в JavaScript?
- Цикл
for...in
используется для перебора ключей объектов, массивов и строк. - Метод
Object.keys()
возвращает массив ключей объекта. - Метод
Object.values()
возвращает значения всех свойств объекта в виде массива. - Метод
Object.entries()
возвращает массив пар ключ-значение объекта.
Метод Object.keys() был добавлен в ES6, тогда как Object.entries() и Object.values() методы были добавлены в ES8. Эти методы преобразуют объект в массив, а затем используют методы цикла массива для перебора этого массива.
Самый простой и популярный способ перебора ключей и значений объекта — использование for…in цикла:
const birds = { owl: '🦉', eagle: '🦅', duck: '🦆', chicken: '🐔' } for (const key in birds) { console.log(`${key} -> ${birds[key]}`) } // owl -> 🦉 // eagle -> 🦅 // duck -> 🦆 // chicken -> 🐔
Единственная проблема с for…in циклом заключается в том, что он перебирает свойства в цепочке прототипов. Поскольку объект JavaScript наследует свойства своего прототипа , for…in цикл также будет перебирать эти свойства. Однако вы можете использовать этот hasOwnProperty()
метод для исключения унаследованных свойств :for (const key in birds) {
if (birds.hasOwnProperty(key)) {
console.log(
${key} -> ${birds[key]})
}
}
Метод Object.keys()
принимает объект в качестве входных данных и возвращает массив имен собственных перечисляемых свойств объекта:const birds = {
owl: '🦉',
eagle: '🦅',
duck: '🦆',
chicken: '🐔'
}
const keys = Object.keys(birds)
console.log(keys)
// [ 'owl', 'eagle', 'duck', 'chicken' ]
Теперь мы можем использовать forEach()цикл для перебора массива и получения значения каждого свойства:
keys.forEach(key => {
console.log(
${key} -> ${birds[key]})
})
// owl -> 🦉
// eagle -> 🦅
// duck -> 🦆
// chicken -> 🐔