Типи даних і перевірка типів є основними аспектами будь-якої мови програмування.
Багато мов програмування, таких як Java, мають сувору перевірку типу. Це означає, що якщо змінна визначена з певним типом, вона може містити значення лише цього типу.
Однак JavaScript - це вільно введена (або динамічно набрана) мова. Це означає, що змінна може містити значення будь-якого типу. Код JavaScript може виконуватися так:
let one = 1; one = 'one'; one = true; one = Boolean(true); one = String('It is possible');
З огляду на це, критично важливо знати тип змінної в будь-який момент часу.
Тип змінної визначається типом присвоєного їй значення. У JavaScript є спеціальний оператор, typeof
який називається типом будь-якого значення.
У цій статті ми дізнаємося, як typeof
це застосовується, а також кілька помилок, на які слід стежити.
Типи даних JavaScript
Давайте швидко розглянемо типи даних JavaScript, перш ніж копатись в typeof
операторі.
У JavaScript існує сім примітивних типів. Примітив - це дані, які не є об’єктом і не мають методів. Вони є:
- Рядок
- Кількість
- BigInt
- Символ
- Логічна
- невизначений
- нуль
Все інше object
- навіть включаючи array
і function
. Тип об’єкта - це сукупність пар ключ-значення.
Тип оператора JavaScript
typeof
Оператор приймає тільки один операнд (унарний оператор) і оцінює його тип повернення типу у вигляді рядка. Ось як ви використовуєте його, коли оцінюєте тип числа, 007.
typeof 007; // returns 'number'
Існує альтернативний синтаксис typeof
оператора, де ви можете використовувати його як function
:
typeof(operand)
Цей синтаксис корисний, коли потрібно оцінити вираз, а не одне значення. Ось приклад цього:
typeof(typeof 007); // returns 'string'
У наведеному вище прикладі вираз typeof 007
обчислюється номером типу і повертає рядок 'число'. typeof('number')
тоді результати в 'string'
.
Давайте розглянемо ще один приклад, щоб зрозуміти важливість дужок з typeof
оператором.
typeof(999-3223); // returns, "number"
Якщо ви опустите дужку, вона поверне, NaN
(Не число):
typeof 999-3223; // returns, NaN
Це пов’язано з тим, що спочатку у typeof 999
результаті з’явиться рядок «число». Вираз "number" - 32223
приводить до NaN, як це відбувається, коли ви виконуєте операцію віднімання між рядком і числом.
Приклад типу JavaScript
Наступний код показує перевірку типу різних значень за допомогою typeof
оператора.
typeof 0; //'number' typeof +0; //'number' typeof -0; //'number' typeof Math.sqrt(2); //'number' typeof Infinity; //'number' typeof NaN; //'number', even if it is Not a Number typeof Number('100'); //'number', After successfully coerced to number typeof Number('freeCodeCamp'); //'number', despite it can not be coerced to a number typeof true; //'boolean' typeof false; //'boolean' typeof Boolean(0); //'boolean' typeof 12n; //'bigint' typeof ''; //'string' typeof 'freeCodeCamp'; //'string' typeof `freeCodeCamp is awesome`; //'string' typeof '100'; //'string' typeof String(100); //'string' typeof Symbol(); //'symbol' typeof Symbol('freeCodeCamp'); //'symbol' typeof {blog: 'freeCodeCamp', author: 'Tapas A'}; //'object'; typeof ['This', 'is', 101]; //'object' typeof new Date(); //'object' typeof Array(4); //'object' typeof new Boolean(true); //'object'; typeof new Number(101); //'object'; typeof new String('freeCodeCamp'); //'object'; typeof new Object; //'object' typeof alert; //'function' typeof function () {}; //'function' typeof (() => {}); //'function' - an arrow function so, parenthesis is required typeof Math.sqrt; //'function' let a; typeof a; //'undefined' typeof b; //'undefined' typeof undefined; //'undefined' typeof null; //'object'
У таблиці нижче наведено можливі значення повернення typeof
:
Тип | Повернене значення typeof |
---|---|
Рядок | 'string' |
Кількість | 'number' |
BigInt | 'bigint' |
Символ | 'symbol' |
Логічна | 'boolean' |
невизначений | 'undefined' |
Об'єкт функції | 'function' |
нуль | 'object' (Дивіться нижче!) |
Будь-які інші предмети | 'object' |
Поширені готи з typeof
Бувають випадки, коли typeof
оператор може не повертати типи, які ви очікували. Це може спричинити плутанину та помилки. Ось кілька випадків.
Тип NaN - це число
typeof NaN; //'number', even if it is Not a Number
typeof NaN
Це 'number'
. Це дивно, оскільки ми не повинні виявляти NaN
використання typeof
. Є кращі способи боротьби з цим. Ми побачимо їх за хвилину.
Тип null
- це об’єкт
typeof null; //'object'
In JavaScript, typeof null
is an object which wrongly suggests that null is an object where it is a primitive value.
This is actually a bug in the language and an attempt was made to fix it. But it was rejected because of backward compatibility issues.
The type of an undeclared variable is undefined
Before ES6, a type check on an undeclared variable used to result in 'undefined'
. But this is not an error-safe way to deal with it.
With ES6 we can declare block-scoped variables with the let
or const
keywords. If you se them with the typeof operator before they are initialized, they will throw a ReferenceError
.
typeof cat; // ReferenceError let cat = 'brownie';
The type of a constructor function is an object
All constructor functions, except for the Function
constructor, will always be typeof
'object'.
typeof new String('freeCodeCamp'); //'object'
This may lead to some confusion, as we expect it to be the actual type (in the above example, a string
type).
The type of an Array is an object
Though technically correct, this could be the most disappointing one. We want to differentiate between an Array and Object even if an Array is technically an Object in JavaScript.
typeof Array(4); //'object'
Fortunately there are ways to detect an Array correctly. We will see that soon.
Beyond typeof
– Better Type Checking
Now that we've seen some of the limitations with the typeof
operator, let's see how to fix them and do better type checking.
How to Detect NaN
In JavaScript, NaN
is a special value. The value NaN represents an outcome when the result of an arithmetic expression can not be represented. For example,
let result = 0/0; console.log(result); // returns, NaN
Also, if we perform any arithmetic operations that involve NaN
, it will always result in a NaN
.
console.log(NaN + 3); // returns, NaN
The type checking on NaN using the typeof
operator doesn't help much as it returns the type as a 'number'
. JavaScript has a global function called isNaN()
to detect if a result is NaN.
isNaN(0/0); // returns, true
But there is a problem here, too.
isNaN(undefined); // returns true for 'undefined'
In ES6, the method isNaN()
is added to the global Number
object. This method is much more reliable and so it's the preferred one.
Number.isNaN(0/0); // returns, true Number.isNaN(undefined); // returns, false
Another interesting aspect of NaN
is that it is the only JavaScript value that is never equal to any other values including itself. So this is another way to detect NaN for the environments where ES6 is not supported:
function isNaN (input) { return input !== input; }
How to Detect null in JavaScript
As we have seen, detecting null using the typeof
operator is not useful. The preferred way to check if something is null is by using the strict equality operator(===
).
function isNull(input) { return input === null; }
Make sure not to use the ==
by mistake. Using the ==
in place of ===
will result in misleading type detection.
How to Detect an Array in JavaScript
From ES6 onwards, we can detect an array using the Array.isArray
method.
Array.isArray([]); // returns true Array.isArray({}); // returns false
Prior to ES6, we could use the instanceof
operator to determine an Array:
function isArray(input) { return input instanceof Array; }
A Generic Solution to Type Checking in JavaScript
There is a way we can create a generic solution to type checking. Have a look at the method, Object.prototype.toString
. This is very powerful and extremely useful for writing a utility method for type checking.
When Object.prototype.toString
is invoked on a value using call()
or apply()
, it returns the object type in the format: [object Type]
. The Type
in the return value is the actual type.
Let's see how it works with some examples:
// returns '[object Array]' Object.prototype.toString.call([]); // returns '[object Date]' Object.prototype.toString.call(new Date()); // returns '[object String]' Object.prototype.toString.call(new String('freeCodeCamp')); // returns '[object Boolean]' Object.prototype.toString.call(new Boolean(true)); // returns '[object Null]' Object.prototype.toString.call(null);
So this means that if we just take the return string and take out the Type
part, we will have the actual type. Here is an attempt to do this:
function typeCheck(value) { const return_value = Object.prototype.toString.call(value); // we can also use regex to do this... const type = return_value.substring( return_value.indexOf(" ") + 1, return_value.indexOf("]")); return type.toLowerCase(); }
Now, we can use the typeCheck
function to detect the types:
typeCheck([]); // 'array' typeCheck(new Date()); // 'date' typeCheck(new String('freeCodeCamp')); // 'string' typeCheck(new Boolean(true)); // 'boolean' typeCheck(null); // 'null'
In Summary
To Summarize what we've learned in this article:
- JavaScript type checking is not as strict as other programming languages.
- Use the
typeof
operator for detecting types. - There are two variants of the
typeof
operator syntax:typeof
andtypeof(expression)
. - The result of a
typeof
operator may be misleading at times. We need to rely on other available methods (Number.isNaN
,Array.isArry
, and so on) in those cases. - We can use
Object.prototype.toString
to create a generic type detection method.
Before we end...
Thank you for reading this far! Let's connect. You can @ me on Twitter (@tapasadhikary) with comments.
You may also like these other articles:
- JavaScript undefined and null: Let's talk about it one last time!
- JavaScript: Equality comparison with ==, === and Object.is
- The JavaScript `this` Keyword + 5 Key Binding Rules Explained for JS Beginners
That's all for now. See you again with my next article soon. Until then, please take good care of yourself.