Контакти

Javascript перевірити тип змінної. Як правильно перевірити тип змінної в JavaScript. Оператор одержання типу typeof

JavaScript або JS (Скорочено) не простий мову і початківці розробники дізнаються про це не відразу. Спочатку вони дізнаються ази і все здається барвистим і прекрасним. Заходячи трохи глибше, з'являються JavaScript масиви, об'єкти, callback'і і все подібне, що часто виносить мозок.

В JavaScript важливо правильно перевіряти тип змінної. Припустимо ви хочете дізнатися чи є змінна масивом або об'єктом? Як це правильно перевірити? У цьому конкретному випадку, є хитрощі під час перевірки і саме про них буде ця запис. Давайте відразу приступимо.

Перевірка типу змінної

Наприклад вам потрібно перевірити є змінна об'єктом, масивом, рядком або числом. Для цього можна використовувати typeof, але вона не завжди видасть правду і в прикладі нижче я покажу чому.

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

Var _comparison \u003d (string: "рядок", int: 99, float: 13.555, object: (hello: "привіт"), array: new Array (1, 2, 3)); // поверне масив з ключами об'єкта var _objKeys \u003d Object.keys (_comparison); for (var i \u003d 0; i<= _objKeys.length - 1; i++) { // выведем в консоль тип каждой переменной console.log(typeof _comparson[_objKeys[i]]); }

Результат виконання коду:

String number number object object

Вірно? - Ні звичайно. Є дві проблеми. Кожна з них буде детально описана і запропоновано рішення.

Перша проблема: float число, виводиться як number

Comparison.float не є числом і замість number має бути float (число з плаваючою точкою) .Щоб це виправити, можна створити функцію з перевіркою як в коді нижче.

Var _floatNumber \u003d 9.22; var _notFloatNumber \u003d 9; console.log (isFloat (_floatNumber)); console.log (isFloat (_notFloatNumber)); console.log (isFloat ( "")); function isFloat (n) (return Number (n) \u003d\u003d\u003d n && n% 1! \u003d\u003d 0;)

Функція isFloat () виконує перевірку всіх значень на числа з плаваючою крапкою. Спочатку перевіряється дорівнює змінна n числу (Number (n) \u003d\u003d\u003d n) і якщо так, то робиться ще одна перевірка на розподіл із залишком і якщо залишок є, то повертається булевої ( true або false) Результат (n% 1! \u003d\u003d 0).

В наведеному вище прикладі вона повертає true, false і false. Перше значення має floatтип, друге немає - це звичайне число і останнім всього лише порожній рядок, яка не підходить під правила.

Друга проблема: масив визначився як об'єкт

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

Є кілька способів для перевірки змінної на тип масиву.

Перший варіант (хороший варіант). Перевіряємо приналежність data до масиву за допомогою instanceof ().

Var data \u003d new Array ( "hello", "world"); var isArr \u003d data instanceof Array;

Другий варіант (хороший варіант). Метод Array.isArray () повертає логічне значення, котре буде залежати від того чи є змінна масивом чи ні ().

Var data \u003d new Array ( "hello", "world"); var isArr \u003d Array.isArray (data);

Третій варіант (найкращий, але довгий). Для зручності, ви можете зробити цей спосіб функцією. Використовуючи Object, ми робимо. Якщо результат Object.prototype.toString.call (data) НЕ дорівнює значить змінна не масив ().

Var data \u003d new Array ( "hello", "world"); var isArr \u003d Object.prototype.toString.call (data) \u003d\u003d ""; console.log (isArr);

Останній результат у вигляді зручної функції:

Function isArray (data) (return Object.prototype.toString.call (data) \u003d\u003d "")

Тепер ви можете викликати функції isArray () і як аргумент задати масив або щось інше і подивитися результат.

Післямова

Запис вийшла досить великою, ніж спочатку замислювалася. Але я їй задоволений, тому що вона досить коротко і чітко описує труднощі при перевірці змінних в JavaScript і як їх обійти.

Якщо у вас залишилися які-небудь питання - пишіть їх нижче до цього запису. Я буду радий допомогти.

оператор typeof повертає рядок, що вказує тип операнда.

синтаксис

Операнд слід за оператором typeof:

Typeof operand

параметри

operand є виразом, що представляє об'єкт або примітив, тип якого повинен бути повернутий.

опис

У наступній таблиці наведені можливі повернені значення typeof. Додаткова інформація про типи і примітивах знаходиться на сторінці.

приклади

// Числа typeof 37 \u003d\u003d\u003d "number"; typeof 3.14 \u003d\u003d\u003d "number"; typeof (42) \u003d\u003d\u003d "number"; typeof Math.LN2 \u003d\u003d\u003d "number"; typeof Infinity \u003d\u003d\u003d "number"; typeof NaN \u003d\u003d\u003d "number"; // незважаючи на те, що це "Not-A-Number» (не число) typeof Number (1) \u003d\u003d\u003d "number"; // ніколи не використовуйте цей запис! // Рядки typeof "" \u003d\u003d\u003d "string"; typeof "bla" \u003d\u003d\u003d "string"; typeof "1" \u003d\u003d\u003d "string"; // зверніть увагу, що число всередині рядка все одно має тип рядка typeof (typeof 1) \u003d\u003d\u003d "string"; // typeof завжди поверне в цьому випадку рядок typeof String ( "abc") \u003d\u003d\u003d "string"; // ніколи не використовуйте цей запис! // Booleans typeof true \u003d\u003d\u003d "boolean"; typeof false \u003d\u003d\u003d "boolean"; typeof Boolean (true) \u003d\u003d\u003d "boolean"; // ніколи не використовуйте цей запис! // Символи typeof Symbol () \u003d\u003d\u003d "symbol" typeof Symbol ( "foo") \u003d\u003d\u003d "symbol" typeof Symbol.iterator \u003d\u003d\u003d "symbol" // Undefined typeof undefined \u003d\u003d\u003d "undefined"; typeof declaredButUndefinedVariable \u003d\u003d\u003d "undefined"; typeof undeclaredVariable \u003d\u003d\u003d "undefined"; // Об'єкти typeof (a: 1) \u003d\u003d\u003d "object"; // використовуйте Array.isArray або Object.prototype.toString.call // щоб розрізнити звичайні об'єкти і масиви typeof \u003d\u003d\u003d "object"; typeof new Date () \u003d\u003d\u003d "object"; // То що нижче призводить до помилок і проблем. Не використовуйте! typeof new Boolean (true) \u003d\u003d\u003d "object"; typeof new Number (1) \u003d\u003d\u003d "object"; typeof new String ( "abc") \u003d\u003d\u003d "object"; // Функції typeof function () () \u003d\u003d\u003d "function"; typeof class C () \u003d\u003d\u003d "function"; typeof Math.sin \u003d\u003d\u003d "function";

null

// Це було визначено з народження JavaScript typeof null \u003d\u003d\u003d "object";

У першій реалізації JavaScript значення були представлені парою тип тега і значення. Тип тега для об'єктів дорівнював 0. null був представлений як нульовий покажчик (0x00 в більшості платформ). Отже, тип тега для null дорівнював нулю, тому що повертається значення typeof є фіктивним. ()

Виправлення було запропоновано в ECMAScript (через відключення), але було відхилено. Це призвело б до того, що typeof null \u003d\u003d\u003d "null".

Використання оператора new

// Все функції-конструктори, створені за допомогою "new", будуть мати тип "object" var str \u003d new String ( "String"); var num \u003d new Number (100); typeof str; // поверне "object" typeof num; // поверне "object" // Але існує виняток для конструктора Function var func \u003d new Function (); typeof func; // поверне "function"

Регулярні вирази

Викликані регулярні вирази були нестандартним доповненням в деяких браузерах.

Typeof / s / \u003d\u003d\u003d "function"; // Chrome 1-12 Не відповідає ECMAScript 5.1 typeof / s / \u003d\u003d\u003d "object"; // Firefox 5+ Відповідає ECMAScript 5.1

Помилки, пов'язані з тимчасовими мертвими зонами

До ECMAScript 2015 року, гарантувалося, що оператор typeof поверне рядок для будь-якого операнда, з яким він був викликаний. Це змінилося після додавання не підіймаються оголошень let and const з блочною областю видимості. Тепер, якщо змінні оголошені за допомогою let і const, і для них викликається typeof в блоці оголошення змінних, але до оголошення, то викидається ReferenceError. Поведінка відрізняється від неоголошених змінних, для яких typeof поверне "undefined". Змінні з блочною областю видимості знаходяться в "тимчасової мертвій зоні", яка триває від початку блоку до моменту оголошення змінних. У цій зоні спроба доступу до змінних викидає виключення.

Typeof undeclaredVariable \u003d\u003d\u003d "undefined"; typeof newLetVariable; let newLetVariable; // ReferenceError typeof newConstVariable; const newConstVariable \u003d "hello"; // ReferenceError

винятки

У всіх поточних браузерах існує нестандартний host-об'єкт document.all, який має тип Undefined.

Typeof document.all \u003d\u003d\u003d "undefined";

Хоча специфікація дозволяє власні імена типів для нестандартних екзотичних об'єктів, потрібно щоб ці імена відрізнялися від зумовлених. Ситуація, коли document.all має тип undefined повинна розглядатися як виключне порушення правил.

специфікації

Специфікація статус Коментарі
ECMAScript Latest Draft (ECMA-262)
чернетка
ECMAScript 2015 (6th Edition, ECMA-262)
Визначення "The typeof Operator" в цій специфікації.
стандарт
ECMAScript 5.1 (ECMA-262)
Визначення "The typeof Operator" в цій специфікації.
стандарт
ECMAScript 3rd Edition (ECMA-262)
Визначення "The typeof Operator" в цій специфікації.
стандарт
ECMAScript 1st Edition (ECMA-262)
Визначення "The typeof Operator" в цій специфікації.
стандарт Початкове визначення. Реалізовано в JavaScript 1.1

Сумісність з браузерами

Update compatibility data on GitHub

Комп'ютериМобільніServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung InternetNode.js
typeofChrome повна підтримка 1 Edge повна підтримка 12 Firefox повна підтримка 1 IE повна підтримка 3 Opera повна підтримка ТакSafari повна підтримка ТакWebView Android повна підтримка 1 Chrome Android повна підтримка 18 Firefox Android повна підтримка 4 Opera Android повна підтримка ТакSafari iOS повна підтримка ТакSamsung Internet Android повна підтримка 1.0 nodejs повна підтримка Так

легенда

повна підтримка повна підтримка

IE-специфічні зауваження

В IE 6, 7 і 8 багато host-об'єкти є об'єктами, але не функціями. Наприклад.

Динамічна ідентифікація типів

Динамічна ідентифікація типів (RTTI) дозволяє визначити тип об'єкта під час виконання програми. Вона виявляється корисною за цілою низкою причин. Зокрема, за посиланням на базовий клас можна досить точно визначити тип об'єкта, доступного за цим посиланням. Динамічна ідентифікація типів дозволяє також перевірити заздалегідь, наскільки вдалим буде результат приведення типів, запобігаючи виняткову ситуацію в зв'язку з неправильним приведенням типів. Крім того, динамічна ідентифікація типів є головною складовою рефлексії.

Для підтримки динамічної ідентифікації типів в C # передбачені три ключових слова: is, as і typeof. Кожне з цих ключових слів розглядається далі по черзі.

оператор is

Конкретний тип об'єкта можна визначити за допомогою оператора is. Нижче наведена його загальна форма:

вираз is тип

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

Нижче наведено приклад застосування оператора is:

Using System; namespace ConsoleApplication1 (class Add () class Sum: Add () class Program (static void Main () (Add a \u003d new Add (); Sum s \u003d new Sum (); if (a is Add) Console.WriteLine ( "Змінна a має тип Add "); if (s is Sum) Console.WriteLine (" Тип змінної s успадкований від класу Add "); Console.ReadLine ();)))

оператор as

Іноді перетворення типів потрібно зробити під час виконання, але не генерувати виняток, якщо результат цього перетворення виявиться невдалим, що цілком можливо при приведенні типів. Для цієї мети служить оператор as, який має таку загальну форму:

вираз as тип

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

Якщо результат такого перетворення виявляється вдалим, то повертається посилання на тип, а інакше - порожня посилання. Оператор as може використовуватися тільки для перетворення посилань, ідентичності, упаковки, розпакування. У деяких випадках оператор as може служити зручною альтернативою оператору is. Як приклад розглянемо наступну програму:

Using System; namespace ConsoleApplication1 (class Add () class Sum: Add () class Program (static void Main () (Add a \u003d new Add (); Sum s \u003d new Sum (); // Виконуємо приведення типів a \u003d s as Add; if (a! \u003d null) Console.WriteLine ( "Перетворення пройшло успішно"); else Console.WriteLine ( "Помилка при перетворенні"); Console.ReadLine ();)))

Результатом виконання даної програми буде успішне перетворення.

a \u003d (b\u003e 0) && (c + 1! \u003d d); flag \u003d! (status \u003d 0);

Таблиця 14.5. Логічні оператори

оператор Опис

! НЕ (логічна інверсія)

&& І (логічне множення)

|| АБО (логічне додавання)

Таблиця 14.6. Результати виконання операторів І і АБО

операнд 1

операнд 2

Таблиця 14.7. Результати виконання оператора НЕ

Оператор одержання типу typeof

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

s \u003d typeof ( "str");

В результаті виконання цього виразу в змінною s виявиться рядок "string", що позначає строковий тип.

Всі значення, які може повернути оператор typeof, перераховані в табл. 14.8.

Таблиця 14.8. Значення, що повертаються оператором typeof

Тип даних

рядок, що повертається

Строковий

числовий

Таблиця 14.8 (закінчення)

Тип даних

рядок, що повертається

логічний

Сумісність і перетворення типів даних

Настала пора розглянути ще два важливих питання: сумісність типів даних і перетворення одного типу до іншого.

Що вийде, якщо скласти два числових значення? Правильно - ще одне числове значення. А якщо скласти число і рядок? Важко сказати ... Тут JavaScript стикається з проблемою несумісності типів даних і намагається зробити ці типи сумісними, перетворюючи один з них до іншого. Спочатку він намагається перетворити рядок в число і, якщо це вдається, можна додавати. У разі невдачі число буде перетворено в рядок, і дві отримані рядки будуть об'єднані. Наприклад, в результаті виконання Web-сценарію з лістингу 14.6 значення змінної b при додаванні зі змінною a буде перетворено в числовий тип; таким чином, змінна c буде містити значення 23.

лістинг 14.6

var a, b, c, d, e, f; a \u003d 11;

b \u003d "12"; c \u003d a + b;

d \u003d "JavaScript"; e \u003d 2;

Але оскільки значення змінної d можна перетворити в число, значення e буде перетворено в рядок, і результат - значення f - стане рівним

Логічні величини перетворюються або в числові, або в рядкові, в залежності від конкретного випадку. Значення true буде перетворено в число 1 або рядок "1", а значення false - в 0 або "0". І навпаки, число 1 буде перетворено в значення true, а число 0 - в значення false. Також в false будуть перетворень

ни значення null і undefined.

Частина III. Поведінка Web-сторінок. Web-сценарії

Видно, що JavaScript щосили намагається правильно виконати навіть некоректно написані вирази. Іноді це виходить, але частіше все працює не так, як планувалося, і, врешті-решт, виконання Web-сценарію переривається у зв'язку з виявленням помилки зовсім в іншому його місці, на абсолютно правильному операторі. Тому краще не допускати подібних казусів.

пріоритет операторів

Останнє питання, яке ми тут розберемо, - пріоритет операторів. Як ми пам'ятаємо, пріоритет впливає на порядок, в якому виконуються оператори в вираженні.

Нехай є такий вираз:

У цьому випадку спочатку до значення змінної b буде додано значення c, а потім з суми буде вирахувано 10. Оператори цього виразу мають однаковий пріоритет і тому виконуються строго зліва направо.

Тепер розглянемо такий вислів:

Тут спочатку буде виконано множення значення c на 10, а вже потім до отриманого добутку буде додано значення b. Оператор множення має більший пріоритет, ніж оператор додавання, тому порядок "строго зліва направо" буде порушений.

Найнижчий пріоритет у операторів присвоювання. Ось чому спочатку обчислюється саме вираження, а потім його результат присвоюється змінної.

В загалом, основний принцип виконання всіх операторів такий: спочатку виконуються оператори з більш високим пріоритетом, а вже потім - оператори з більш низьким. Оператори з однаковим пріоритетом виконуються в порядку їх слідування (зліва направо).

В табл. 14.9 перераховані всі вивчені нами оператори в порядку убування їх пріоритетів.

Таблиця 14.9. Пріоритет операторів (в порядку убування)

Оператори

опис

++ - - ~! typeof

Інкремент, декремент, зміна знака, логічне НЕ, визначення типу

Множення, ділення, взяття залишку

Додавання і об'єднання рядків, віднімання

Оператори порівняння

логічне І

Глава 14. Введення в Web-програмування. Мова JavaScript

Таблиця 14.9 (закінчення)

Оператори

опис

логічне АБО

Умовний оператор (див. Нижче)

= <оператор>=

Присвоєння, просте і складне

УВАГА!

Запам'ятайте цю таблицю. Неправильний порядок виконання операторів може стати причиною важко виявляються помилок, при яких зовні абсолютно правильне вираз дає невірний результат.

Але що робити, якщо нам потрібно порушити звичайний порядок виконання операторів? Скористаємося дужками. При такому записі укладені в дужки оператори виконуються першими:

a \u003d (b + c) * 10;

Тут спочатку буде виконано складання значень змінних b і c, а потім вийшла сума буде помножена на 10.

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

a \u003d ((b + c) * 10 - d) / 2 + 9;

Тут оператори будуть виконані в такій послідовності:

1. Додавання b і c.

2. Множення отриманої суми на 10.

3. Віднімання d з твору.

4. Розподіл різниці на 2.

5. Додаток 9 до приватного.

Якщо видалити дужки:

a \u003d b + c * 10 - d / 2 + 9;

то порядок виконання операторів буде таким:

1. Множення c і 10.

2. Розподіл d на 2.

3. Складання b і твори c і 10.

4. Віднімання з отриманої суми частки від розподілуd на 2.

5. Додаток 9 до отриманої різниці.

Виходить зовсім інший результат, чи не так?



Сподобалася стаття? поділіться їй