JavaScript TypeOf - Πώς να ελέγξετε τον τύπο μιας μεταβλητής ή αντικειμένου στο JS

Οι τύποι δεδομένων και ο έλεγχος τύπων είναι θεμελιώδεις πτυχές οποιασδήποτε γλώσσας προγραμματισμού.

Πολλές γλώσσες προγραμματισμού όπως η Java έχουν αυστηρό έλεγχο τύπου. Αυτό σημαίνει ότι εάν μια μεταβλητή ορίζεται με έναν συγκεκριμένο τύπο μπορεί να περιέχει μια τιμή μόνο αυτού του τύπου.

Η JavaScript, ωστόσο, είναι μια χαλαρά πληκτρολογημένη (ή δυναμικά δακτυλογραφημένη) γλώσσα. Αυτό σημαίνει ότι μια μεταβλητή μπορεί να περιέχει τιμή οποιουδήποτε τύπου. Ο κώδικας JavaScript μπορεί να εκτελεστεί ως εξής:

let one = 1; one = 'one'; one = true; one = Boolean(true); one = String('It is possible'); 

Έχοντας αυτό κατά νου, είναι σημαντικό να γνωρίζετε τον τύπο μιας μεταβλητής ανά πάσα στιγμή.

Ο τύπος μιας μεταβλητής καθορίζεται από τον τύπο της τιμής που της έχει ανατεθεί. Το JavaScript έχει έναν ειδικό χειριστή που ονομάζεται typeofπου σας επιτρέπει να λάβετε τον τύπο οποιασδήποτε τιμής.

Σε αυτό το άρθρο, θα μάθουμε πώς typeofχρησιμοποιείται, μαζί με μερικά gotchas που πρέπει να προσέξετε.

Τύποι δεδομένων JavaScript

Ας ρίξουμε μια γρήγορη ματιά στους τύπους δεδομένων JavaScript προτού ανακαλύψουμε τον typeofχειριστή.

Στο JavaScript, υπάρχουν επτά πρωτόγονοι τύποι. Ένα πρωτόγονο είναι δεδομένα που δεν είναι αντικείμενο και δεν έχει μεθόδους. Αυτοί είναι:

  1. Σειρά
  2. Αριθμός
  3. BigInt
  4. Σύμβολο
  5. Boolean
  6. απροσδιόριστος
  7. μηδενικό

Όλα τα άλλα είναι object- ακόμη και συμπεριλαμβανομένων arrayκαι function. Ένας τύπος αντικειμένου είναι μια συλλογή ζευγών κλειδιού-τιμής.

Ο τύπος JavaScript του χειριστή

Ο typeofχειριστής παίρνει μόνο έναν τελεστή (ένας unary τελεστής) και αξιολογεί τον τύπο του για να επιστρέψει τον τύπο ως συμβολοσειρά. Εδώ είναι πώς το χρησιμοποιείτε όταν αξιολογείτε τον τύπο ενός αριθμού, 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". Η έκφραση "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 'boolean'
απροσδιόριστος 'undefined'
Αντικείμενο λειτουργίας 'function'
μηδενικό 'object'(Δες παρακάτω!)
Οποιαδήποτε άλλα αντικείμενα 'object'

Κοινή Gotchas με 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 and typeof(expression).
  • Το αποτέλεσμα ενός typeofχειριστή μπορεί μερικές φορές να είναι παραπλανητικό. Θα πρέπει να βασίζονται σε άλλες διαθέσιμες μεθόδους ( Number.isNaN,   Array.isArry, και ούτω καθεξής), σε αυτές τις περιπτώσεις.
  • Μπορούμε να χρησιμοποιήσουμε Object.prototype.toStringγια να δημιουργήσουμε μια μέθοδο ανίχνευσης γενικού τύπου.

Πριν τελειώσουμε ...

Ευχαριστούμε που διαβάσατε μέχρι τώρα! Ας συνδεθούμε. Μπορείτε να μου @ στο Twitter (@tapasadhikary) με σχόλια.

Μπορεί επίσης να σας αρέσουν αυτά τα άλλα άρθρα:

  • Απροσδιόριστη και μηδενική JavaScript: Ας μιλήσουμε για τελευταία φορά!
  • JavaScript: Σύγκριση ισότητας με ==, === και Object.is
  • Η λέξη-κλειδί JavaScript «this» + 5 βασικοί κανόνες δέσμευσης που εξηγούνται για αρχάριους JS

Αυτα για τωρα. Θα τα πούμε ξανά με το επόμενο άρθρο μου σύντομα. Μέχρι τότε, φροντίστε τον εαυτό σας.