diff --git a/js/instanceof/demos/basic/index.html b/js/instanceof/demos/basic/index.html new file mode 100644 index 0000000000..b272f69e61 --- /dev/null +++ b/js/instanceof/demos/basic/index.html @@ -0,0 +1,492 @@ + + + + Интерактивная демка оператора instanceof — Оператор instanceof — Дока + + + + + + + + +
+

instanceof

+ +
+
+ [] + Array → true +
+
+ [] + Object → true +
+
+ Date + Date → true +
+
+ Date + Array → false +
+
+ { } + Object → true +
+
+ { } + Array → false +
+
+ fn() + Function → false +
+
+ fn() + Object → true +
+
+ +
+
+ + + +
+ +
+ + + + + + + + +
+ +
+ instanceof + ["123"] instanceof Array + + true +
+
+ +
+ 💡 instanceof работает только с объектами. Для примитивов (числа, строки, boolean) всегда возвращает false. +
+
+ + + + diff --git a/js/instanceof/index.md b/js/instanceof/index.md new file mode 100644 index 0000000000..71caf139db --- /dev/null +++ b/js/instanceof/index.md @@ -0,0 +1,159 @@ +--- +title: "Оператор `instanceof`" +description: "Оператор instanceof проверяет, принадлежит ли объект определённому классу. Как проверить тип объекта и отличить массив от объекта, дату от промиса" +authors: + - drakesbot12 +keywords: + - instanceof + - оператор instanceof + - проверка типа объекта + - классы javascript + - наследование javascript + - prototype +related: + - js/typeof + - js/function + - js/object +tags: + - doka +--- + +## Кратко + +Оператор `instanceof` проверяет, принадлежит ли объект определённому классу или конструктору. Он возвращает `true`, если объект был создан с помощью этого конструктора или наследуется от него. + +## Пример + + + +## Как пишется + +`instanceof` — это бинарный оператор. Он проверяет цепочку прототипов объекта и ищет в ней свойство `prototype` указанного конструктора: + +```js +объект instanceof Конструктор +``` + +JavaScript поднимается по цепочке прототипов объекта и проверяет, встречается ли там `Конструктор.prototype`. Если встречается — возвращает `true`, если дошёл до конца цепочки и не нашёл — `false`. + +```js +class Animal {} +class Dog extends Animal {} + +const rex = new Dog() + +rex instanceof Dog // true — в цепочке есть Dog.prototype +rex instanceof Animal // true — в цепочке есть Animal.prototype +rex instanceof Object // true — в цепочке есть Object.prototype +``` + +## Как понять + +### Для чего нужен + +`instanceof` помогает определить, с каким именно объектом мы работаем. Это особенно полезно, когда нужно отличить один тип объекта от другого: + +```js +function process(value) { + if (value instanceof Array) { + // Обрабатываем массив + return value.map(item => item * 2) + } + + if (value instanceof Date) { + // Обрабатываем дату + return value.toLocaleString() + } + + if (value instanceof Promise) { + // Обрабатываем промис + return value.then(data => data) + } + + return value +} +``` + +### Примитивы и объекты + +`instanceof` работает только с объектами. Для примитивов он всегда возвращает `false`: + +```js +42 instanceof Number // false +"строка" instanceof String // false +true instanceof Boolean // false + +// Но если создать через конструктор — true +new Number(42) instanceof Number // true +new String("строка") instanceof String // true +``` + +### Наследование + +`instanceof` учитывает наследование — если класс наследует от другого класса, проверка вернёт `true` для обоих: + +```js +class Vehicle {} +class Car extends Vehicle {} + +const tesla = new Car() + +tesla instanceof Car // true +tesla instanceof Vehicle // true +tesla instanceof Object // true +``` + +### Массивы + +Массивы — это объекты, поэтому `instanceof Array` работает, но и `instanceof Object` тоже вернёт `true`: + +```js +[1, 2, 3] instanceof Array // true +[1, 2, 3] instanceof Object // true +``` + +Чтобы точно проверить массив, лучше использовать `Array.isArray()`: + +```js +Array.isArray([1, 2, 3]) // true +``` + +### Функции-конструкторы + +`instanceof` работает и со старыми функциями-конструкторами: + +```js +function Person(name) { + this.name = name +} + +const alice = new Person("Алиса") +alice instanceof Person // true +alice instanceof Object // true +``` + +### Ошибки + +`instanceof` отлично работает с ошибками: + +```js +try { + // что-то ломается +} catch (error) { + if (error instanceof TypeError) { + console.log("Ошибка типа!") + } else if (error instanceof RangeError) { + console.log("Выход за пределы!") + } else { + console.log("Другая ошибка") + } +} +``` + +## Подсказки + +💡 `instanceof` проверяет **наследование**, а не просто конструктор. Если объект был создан с помощью `Object.create()` с другим прототипом — поведение может отличаться. +💡 Для примитивов используйте `typeof`, для объектов — `instanceof`. +💡 `instanceof` может сломаться, если объект был передан между разными фреймами или iframe — там свои глобальные объекты и цепочки прототипов. +💡 В современном коде вместо `instanceof` для проверки конкретных типов часто используют проверку наличия методов: `if (value?.then)` для промисов или `if (Array.isArray(value))` для массивов. +💡 `instanceof` работает с любыми функциями, у которых есть свойство `prototype`. diff --git a/js/typeof/demos/basic/index.html b/js/typeof/demos/basic/index.html new file mode 100644 index 0000000000..880ec9aff7 --- /dev/null +++ b/js/typeof/demos/basic/index.html @@ -0,0 +1,471 @@ + + + + Плейграунд typeof — Оператор typeof — Дока + + + + + + + + +
+

typeof

+ +
+
+ 42 + number +
+
+ "Дока" + string +
+
+ true + boolean +
+
+ undefined + undefined +
+
+ null + object ⚠️ +
+
+ { } + object +
+
+ [ ] + object +
+
+ fn() {} + function +
+
+ Symbol() + symbol +
+
+ 1n + bigint +
+
+ +
+
+ + +
+ +
+ + + + + + + + + + +
+ +
+ typeof + new Set([1, 2, 3]) + + object +
+
+ +
+ ⚠️ null"object" — баг JavaScript. Set, Map, Date, RegExp → тоже "object" +
+
+ + + + diff --git a/js/typeof/index.md b/js/typeof/index.md new file mode 100644 index 0000000000..e64ec75815 --- /dev/null +++ b/js/typeof/index.md @@ -0,0 +1,146 @@ +--- +title: "Оператор `typeof`" +description: "Оператор typeof возвращает строку с типом операнда. Как проверить тип данных в JavaScript и что нужно знать о его особенностях" +authors: + - drakesbot12 +keywords: + - typeof + - оператор typeof + - проверка типа + - тип данных + - javascript typeof + - null typeof +related: + - js/typecasting + - js/number + - js/instanceof +tags: + - doka +--- + +## Кратко + +Оператор `typeof` возвращает строку с типом операнда. Это простой способ проверить, с чем мы имеем дело: число, строка, объект или что-то другое. + +## Пример + + + +## Как пишется + +`typeof` — это унарный оператор. Это значит, что он применяется к одному операнду и записывается перед ним: + +```js +typeof выражение +// или +typeof(выражение) // скобки не обязательны +``` +`typeof` всегда возвращает строку с типом. Вот полный список возможных значений: + +- `"number"` — для чисел; +- `"string"` — для строк; +- `"boolean"` — для логических значений (`true`/`false`); +- `"undefined"` — для undefined; +- `"object"` — для `null` ⚠️ (это баг языка); +- `"object"` — для объектов `{}`; +- `"object"` — для массивов `[]`; +- `"function"` — для функций; +- `"symbol"` — для символов; +- `"bigint"` — для больших целых чисел. + +## Как понять + +### Особенности + +#### Баги + +Главная особенность `typeof`, которую нужно запомнить — `typeof null === "object"`. Это официально признанная ошибка в языке, которая существует с первых версий. Её не исправят, чтобы не сломать существующий код. + +Если нужно проверить значение на `null`, используйте строгое сравнение: + +```js +value === null +``` + +#### Массивы + +Массивы тоже считаются объектами: + +```js +typeof [1, 2, 3] // "object" +``` + +Чтобы проверить, является ли значение массивом, используйте `Array.isArray()`: + +```js +Array.isArray([1, 2, 3]) // true +``` + +### Когда использовать + +#### Базовая проверка типа + +Самый частый сценарий — проверка, что переменная существует и имеет нужный тип: + +```js +function greet(name) { + if (typeof name === "string") { + console.log(`Привет, ${name}!`) + } else { + console.log("Привет, незнакомец!") + } +} +``` + +#### Проверка на undefined + +Проверка, определена ли переменная: + +```js +if (typeof something === "undefined") { + console.log("Переменная не определена") +} +``` + +Важно: если переменная вообще не объявлена, `typeof` не выбросит ошибку, а вернёт `"undefined"`. Это одно из редких мест в JavaScript, где можно безопасно обратиться к несуществующей переменной. + +```js +typeof notDeclared // "undefined" +notDeclared // ReferenceError +``` + +#### Проверка на функцию + +Это удобно, когда вы ожидаете колбэк: + +```js +function doSomething(callback) { + if (typeof callback === "function") { + callback() + } +} +``` + +### Чего не умеет `typeof` + +`typeof` различает только примитивные типы и несколько специальных случаев. Он не поможет: + +- Отличить массив от объекта; +- Отличить дату от обычного объекта; +- Отличить регулярное выражение от объекта; +- Проверить, является ли значение экземпляром класса. + +Для таких проверок используйте [`instanceof`](/js/instanceof/) или специальные методы: + +```js +const date = new Date() +date instanceof Date // true +Array.isArray([]) // true +``` + +## Подсказки + +💡 Проверка на `null` делается через строгое сравнение: `value === null`, а не через `typeof`. +💡 `typeof` безопасен для необъявленных переменных, в отличие от прямого обращения к ним. +💡 В TypeScript `typeof` работает на уровне типов и используется совсем иначе — не путайте с оператором JavaScript. +💡 Для проверки на объект можно использовать `typeof value === "object" && value !== null`, чтобы исключить `null`.