Javascript check variable type. How to properly check the type of a variable in JavaScript

JavaScript or JS(abbreviated) is not an easy language and novice developers will not learn about it right away. At first they learn the basics and everything seems colorful and beautiful. Going a little deeper, they appear JavaScript arrays, objects, callbacks and all that stuff that often blows your mind.

In JavaScript, it is important to properly check the type of a variable. Let's say you want to know whether a variable is an array or an object? How to check this correctly? In this particular case, there are tricks during verification and this post will be about them. Let's get started right away.

Checking the type of a variable

For example, you need to check whether a variable is an object, an array, a string or a number. You can use typeof for this, but it will not always tell the truth and in the example below I will show why.

I wrote this example to clearly show why typeof is not always the right choice.

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

Result of executing the code:

String number number object object

Right? - Of course not. There are two problems. Each of them will be described in detail and a solution proposed.

First problem: float number, output as number

Comparison.float is not a number and number should be a float (floating point number). To fix this, you can create a function with a check as in the code below.

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

The isFloat() function checks that all values ​​are floating point. First, it is checked whether the variable is equal to n number (Number(n) === n) and if yes, then another check is made for division with a remainder and if there is a remainder, then a boolean ( true or false) result (n % 1 !== 0).

In the example above it returns true, false And false. The first meaning is float type, the second one is not - it's a regular number and the last one is just an empty string that doesn't fit the rules.

Second problem: the array was defined as an object

In the very first example, the array was displayed as an object and this is not very good, since sometimes you need to use exactly this type and nothing else.

There are several ways to check if a variable is an array type.

First option (good option). We check whether data belongs to an array using instanceof().

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

Second option (good option). The Array.isArray() method returns a boolean value that will depend on whether the variable is an array or not ().

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

Third option (the best, but long). For convenience, you can make this method a function. Using Object we do . If the result of Object.prototype.toString.call(data) is not equal, then the variable is not an array ().

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

The last result in the form of a convenience function:

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

Now you can call the isArray() functions and set an array or something else as an argument and see the result.

Afterword

The recording turned out to be quite large than originally intended. But I'm pleased with it because it quite succinctly and clearly describes the difficulties when checking variables in JavaScript and how to get around them.

If you still have any questions, write them below to this entry. I'll be happy to help.

Dynamic type identification

Dynamic Type Identification (RTTI) allows you to determine the type of an object during program execution. It turns out to be useful for a number of reasons. In particular, using a reference to a base class, you can quite accurately determine the type of object accessible through this reference. Dynamic type identification also allows you to check in advance how successful a type cast will be, preventing an exception due to an incorrect type cast. In addition, dynamic type identification is a major component of reflection.

To support dynamic type identification, C# provides three keywords: is, as, and typeof. Each of these keywords is discussed below in turn.

is operator

The specific type of an object can be determined using the is operator. Below is its general form:

expression is type

where expression denotes a single expression describing the object whose type is being tested. If the expression is of a compatible or the same type as the type being tested, then the result of this operation is true, otherwise it is false. Thus, the result will be true if the expression has a type being tested in one form or another. The is operator defines both types as compatible if they are the same type or if reference conversion, boxing, or unboxing is provided.

Below is an example of using the is operator:

Using System; namespace ConsoleApplication1 ( class Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); if (a is Add) Console.WriteLine("Variable a is of type Add"); if (s is Sum) Console.WriteLine("The type of variable s is inherited from the Add class"); Console.ReadLine(); ) ) )

Operator as

Sometimes you want to perform a type conversion at runtime, but not throw an exception if the conversion fails, which is quite possible with type casting. The as operator serves this purpose, having the following general form:

expression as type

where expression denotes a single expression that converts to the specified type.

If the outcome of such a conversion is successful, then a reference to the type is returned, otherwise an empty reference. The as operator can only be used for reference conversion, identity, boxing, unboxing. In some cases, the as operator can be a convenient alternative to the is operator. As an example, consider the following program:

Using System; namespace ConsoleApplication1 ( class Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); // Perform type casting a = s as Add; if (a != null) Console.WriteLine("Conversion was successful"); else Console.WriteLine("Error during conversion"); Console.ReadLine(); ) ) )

The result of executing this program will be a successful conversion.

  • Undefined: "undefined"
  • Null: "object"
  • Boolean: "boolean"
  • Number: "number"
  • String: "string"
  • Function: "function"
  • Everything else: "object"

The following notes should be added to this table:

1. typeof null === "object" .

Theoretically, there is a subtle point here. In statically typed languages, an object type variable may not contain an object (NULL, nil, null pointer).

In practice, this is inconvenient in JavaScript. So the ES 5.1 developers are going to do something more intuitive: typeof null === "null" .

But since we still have ES3 all around, don’t be mistaken, for example, with this:

/* The function searches for some object and returns it or null if nothing is found */ function search() () var obj = search(); if (typeof obj === "object") ( // did we really find the object (FAIL) obj.method(); )

2. Don’t forget about wrapper objects (typeof new Number(5) === “object”).

3. And don’t forget about the right of browsers to do whatever they want with host objects.

Don’t be surprised that Safari stubbornly considers HTMLCollection to be a function type, and IE earlier than version 9 keeps our favorite alert() function as an object . Also, Chrome used to consider RegExp to be a function , but now it seems to come to its senses and respond to it with object .

toString()

Trying to find out the type of a value from the result of its toString() method is pointless. In all “classes” this method is overridden to its own.

The method is good for displaying debugging information, but it cannot be used to determine the type of a variable.

Object.prototype.toString()

Although toString is overridden within specific “classes,” we still have its original implementation from Object. Let's try to use it:

console.log(Object.prototype.toString.call(value));

console.log(Object.prototype.toString.call(value));


Clinton lightens up this tediousness

Oddly enough, this method works surprisingly well.

For scalar types, returns , , , .

The funny thing is that even new Number(5) on which typeof failed here returns .

The method fails on null and undefined. Different browsers return, sometimes expected and sometimes, sometimes in general. However, you can easily determine the type of these two values ​​without this.

Things get interesting when we come to objects (those with typeof === "object").

built-in objects work practically with a bang:

  • {} —
  • Date -
  • Error —
  • RegExp —

The only thing is that it falls out of the list of arguments, which is either .
Things are getting worse again with host objects.

In IE, DOM objects began to become “normal” objects only from version 8, and even then not completely. Therefore, in IE 6-8, all these objects (HTMLCOllection, DOMElement, TextNode, and at the same time document and window) are simply reduced to .

In all other browsers (including IE9), you can already do something with the result of toString. Although everything is also not easy: HTMLCollection is there, then . window - then, then, then. But you can already try to get something out of this.

It’s more complicated with DOMElement: it is displayed in the form, - a different format for each tag. But the regular season will help us here too.

The story is approximately the same with other host objects (in the location and navigator tests). Everywhere except IE, they can be identified by the line.

Disadvantages of using Object.prototype.toString():

1. This possibility is not covered by the standard. And here we should rather be happy that everything is working so well, rather than lamenting about some of the shortcomings.

2. Determining a type by parsing a string returned by a method that is not used to determine a type at all, and is also called on an object to which it does not relate, leaves some sediment in the soul.

3. In old IE, as you can see, it is normal not to identify host objects.

However, this is a completely working thing when used in conjunction with other means.


Constructors

And finally, the designers. Who better to say about the "class" of an object in JS than its constructor?

null and undefined have neither wrapper objects nor constructors.

Other scalar types have wrappers, so you can also get a constructor:

(5).constructor === Number; (Number .NaN ) .constructor === Number ; (true).constructor === Boolean; ("string").constructor === String;

(5).constructor === Number; (Number.NaN).constructor === Number; (true).constructor === Boolean; ("string").constructor === String;

But instanceof will not work here:

5 instanceof Number ; // false Number .NaN instanceof Number ; // false true instanceof Boolean ; // false "string" instanceof String ; // false

5 instanceof Number; // false Number.NaN instanceof Number; // false true instanceof Boolean; // false "string" instanceof String; // false

(instanceof will work for the long-suffering new Number(5))

With functions (which are also objects) instanceof will work:

console.log ( (function () ( ) ) instanceof Function ) ; // true console.log ( (function () ( ) ).constructor === Function ) ; // true

console.log((function () ()) instanceof Function); // true console.log((function () ()).constructor === Function); // true

All objects of built-in classes are also easily identified by their constructors: Array, Date, RegExp, Error.

One problem arises here with arguments , whose constructor is Object .

And the second is with Object itself, or rather, how to assign an object created through a custom constructor to it.

This way you can define only the base object:

obj instanceof Object;

One of the definition options is to go through all the other possible types (Array, Error...) and if none of them fit - “object”.

Constructors and host objects

Things get worse with host objects.

Let's start with the fact that IE up to and including version 7 does not consider them normal objects at all. They simply don’t have designers and prototypes there (in any case, a programmer can’t reach them).

Things are better in other browsers. There are constructors and you can use them to determine the class of a value. They are just called differently in different browsers. For example, for an HTMLCollection the constructor will be either an HTMLCollection or a NodeList, or even a NodeListConstructor.

You should also define a base constructor for DOMElement. In FF, this is, for example, HTMLElement , from which HTMLDivElement and others already inherit.

The trick is thrown at FireFox below version 10 and Opera below 11. The collection constructor there is Object .

constructor.name

Constructors also have a name property, which can be useful.

It contains the name of the constructor function, for example, (5).constructor.name === "Number" .

However:
1. It doesn’t exist in IE at all, even in 9.
2. Browsers again create whatever they want into Host objects (and often they don’t have this property at all). In Opera, DOMElement’s constructor name is generally Function.prototype .
3. arguments again “object”.

conclusions

None of the presented methods provides a 100% determination of the type/class of a value in all browsers. However, taken together they make it possible to do this.

In the near future I will try to collect all the data into tables and give an example of a definition function.

Internet