Maison / Maîtriser l'ordinateur / Type de variable de contrôle Javascript. obtenir le type d'opérateur

Type de variable de contrôle Javascript. obtenir le type d'opérateur

Javascript ou JS(sous peu) pas un langage facile et les développeurs novices ne l'apprendront pas tout de suite. Au début, ils apprennent les bases et tout semble coloré et beau. En approfondissant un peu, il y a Tableaux JavaScript, des objets, des rappels et tout ce qui vous étonne souvent.

En JavaScript, il est important de vérifier correctement le type d'une variable. Disons que vous voulez savoir si une variable est un tableau ou un objet ? Comment le vérifier correctement ? Dans ce cas particulier, il existe des astuces lors de la vérification et c'est de cela que va parler cet article. Commençons tout de suite.

Vérification du type d'une variable

Par exemple, vous devez vérifier si une variable est un objet, un tableau, une chaîne ou un nombre. Vous pouvez utiliser typeof pour cela, mais cela ne vous dira pas toujours la vérité, et je vais vous montrer pourquoi dans l'exemple ci-dessous.

J'ai écrit cet exemple pour illustrer pourquoi typeof n'est pas toujours le bon choix.

Var _comparison = ( string : "string", int : 99, float : 13,555, object : (hello : "hello"), array : new Array(1, 2, 3) ); // Retourne un tableau avec les clés de l'objet var _objKeys = Object.keys(_comparison); pour(var je = 0; je<= _objKeys.length - 1; i++) { // выведем в консоль тип каждой переменной console.log(typeof _comparson[_objKeys[i]]); }

Résultat de l'exécution du code :

Objet objet numéro de chaîne

Droit? - Bien sûr que non. Il y a deux problèmes. Chacun d'eux sera décrit en détail et une solution proposée.

Premier problème : nombre flottant, sortie sous forme de nombre

Comparaison.float n'est pas un nombre et devrait être un flottant au lieu d'un nombre. Pour résoudre ce problème, vous pouvez créer une fonction avec une vérification comme dans le code ci-dessous.

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; )

La fonction isFloat() vérifie toutes les valeurs pour les nombres à virgule flottante. Vérifiez d'abord si la variable est égale n nombre (Nombre(n) === n) et si oui, alors une autre vérification est faite pour la division avec un reste et s'il y a un reste, alors un booléen est retourné ( vrai ou faux) résultat (n % 1 !== 0).

Dans l'exemple ci-dessus, il renvoie vrai, faux et faux. Le premier sens est flotteur type, le second ne l'est pas - il s'agit d'un nombre normal et le dernier n'est qu'une chaîne vide qui ne respecte pas les règles.

Deuxième problème : le tableau a été défini comme un objet

Dans le tout premier exemple, le tableau est rendu sous la forme d'un objet, ce qui n'est pas très bon, car parfois vous devez utiliser ce type et rien d'autre.

Il existe plusieurs façons de tester une variable pour un type de tableau.

La première option (bonne option). Vérifiez si les données appartiennent à un tableau en utilisant instanceof().

Var data = new Array("bonjour", "monde"); var isArr = instance de données du tableau ;

La deuxième option (bonne option). La méthode Array.isArray() retourne une valeur booléenne qui dépendra si la variable est un tableau ou non().

Var data = new Array("bonjour", "monde"); var isArr = Array.isArray(data);

La troisième option (la meilleure, mais longue). Pour plus de commodité, vous pouvez faire de cette méthode une fonction. En utilisant Object nous faisons . Si le résultat de Object.prototype.toString.call(data) n'est pas égal, alors la variable n'est pas un tableau ().

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

Le dernier résultat en tant que fonction de commodité :

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

Vous pouvez maintenant appeler les fonctions isArray() et définir un tableau ou quelque chose comme argument et voir le résultat.

Épilogue

Le disque s'est avéré être assez volumineux par rapport à ce qui était initialement prévu. Mais j'en suis satisfait car il est suffisamment concis et clair pour décrire les difficultés de validation des variables en JavaScript et comment les contourner.

Si vous avez des questions, veuillez les poster sous ce post. Je serai ravi de vous aider.

a = (b > 0) && (c + 1 != d); drapeau = !(statut = 0);

Tableau 14.5. Opérateurs logiques

Description de l'opérateur

! NON (inversion logique)

&& ET (multiplication booléenne)

|| OU (addition logique)

Tableau 14.6. Résultats de l'exécution des opérateurs AND et OR

Opérande 1

Opérande 2

Tableau 14.7. Résultats de l'exécution de l'instruction NOT

obtenir le type d'opérateur

Obtenir l'opérateur de type typeof renvoie une chaîne décrivant le type de données de l'opérande. L'opérande dont le type est à rechercher est placé après cet opérateur et entre parenthèses :

s = typeof("str");

À la suite de cette expression, la variable s contiendra la chaîne "string" , indiquant le type de chaîne.

Toutes les valeurs que l'opérateur typeof peut renvoyer sont répertoriées dans le tableau 1. 14.8.

Tableau 14.8. Valeurs renvoyées par l'opérateur typeof

Type de données

Chaîne de retour

Chaîne de caractères

Numérique

Tableau 14.8 (fin)

Type de données

Chaîne de retour

Logique

Compatibilité et conversion de type de données

Il est temps d'examiner deux problèmes plus importants : la compatibilité des types de données et la conversion d'un type à un autre.

Que se passe-t-il lorsque vous additionnez deux nombres ? C'est vrai - une autre valeur numérique. Et si vous ajoutiez un nombre et une chaîne ? C'est difficile à dire... Ici, JavaScript se heurte au problème de l'incompatibilité des types de données et essaie de rendre ces types compatibles en convertissant l'un d'entre eux en un autre. Il essaie d'abord de convertir la chaîne en un nombre et, s'il réussit, effectue l'addition. En cas d'échec, le nombre sera converti en une chaîne et les deux chaînes résultantes seront concaténées. Par exemple, le script Web du Listing 14-6 convertirait la valeur de la variable b lorsqu'elle est ajoutée à la variable a en un type numérique ; ainsi la variable c contiendra la valeur 23.

Liste 14.6

var a, b, c, d, e, f ; un = 11 ;

b = "12" ; c = un + b ;

d="JavaScript" ; e = 2 ;

Mais comme la valeur de la variable d ne peut pas être convertie en nombre, la valeur de e sera convertie en chaîne et le résultat - la valeur de f - deviendra égal à

Les valeurs booléennes sont converties en valeurs numériques ou de chaîne, selon le cas. True sera converti en nombre 1 ou en chaîne "1" , et false en 0 ou "0" . A l'inverse, le nombre 1 sera converti en true et le nombre 0 en false . De plus, false sera converti

nous sommes nuls et indéfinis.

Partie III. Comportement des pages Web. Scripts Web

On peut voir que JavaScript a du mal à exécuter correctement des expressions même mal écrites. Parfois, cela fonctionne, mais le plus souvent, les choses ne se passent pas comme prévu, et finalement le script Web est abandonné en raison d'une erreur trouvée à un endroit complètement différent du script, sur l'instruction absolument correcte. Par conséquent, il vaut mieux éviter de tels incidents.

Priorité des opérateurs

Le dernier problème que nous traiterons ici est la priorité des opérateurs. Comme nous nous en souvenons, la priorité affecte l'ordre dans lequel les opérateurs d'une expression sont exécutés.

Soit l'expression suivante :

Dans ce cas, la valeur de c sera d'abord ajoutée à la valeur de la variable b, puis la somme sera soustraite de 10. Les opérateurs de cette expression ont la même priorité et sont donc exécutés strictement de gauche à droite.

Considérons maintenant cette expression :

Ici, d'abord, la valeur c sera multipliée par 10, puis seulement la valeur b sera ajoutée au produit résultant. L'opérateur de multiplication a une priorité plus élevée que l'opérateur d'addition, donc l'ordre "strictement de gauche à droite" sera violé.

Les opérateurs d'affectation ont la priorité la plus faible. C'est pourquoi l'expression elle-même est évaluée en premier, puis son résultat est affecté à une variable.

À En général, le principe de base de l'exécution de tous les opérateurs est le suivant : les opérateurs avec une priorité plus élevée sont exécutés en premier, et seulement ensuite - les opérateurs avec une priorité inférieure. Les opérateurs de même priorité sont exécutés dans l'ordre dans lequel ils apparaissent (de gauche à droite).

À languette. 14.9 liste tous les opérateurs que nous avons étudiés par ordre décroissant de leur précédence.

Tableau 14.9. Priorité des opérateurs (par ordre décroissant)

Les opérateurs

La description

++ -- - ~ ! Type de

Incrémentation, décrémentation, changement de signe, NON logique, inférence de type

Multiplication, division, reste

Addition et concaténation de chaînes, soustraction

Opérateurs de comparaison

ET logique

Chapitre 14. Introduction à la programmation Web. Langage JavaScript

Tableau 14.9 (fin)

Les opérateurs

La description

OU logique

Opérateur conditionnel (voir ci-dessous)

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

Mission, simple et complexe

ATTENTION!

Rappelez-vous ce tableau. Un ordre d'exécution incorrect des instructions peut provoquer des erreurs difficiles à détecter, dans lesquelles une expression apparemment absolument correcte donne un résultat incorrect.

Mais que se passe-t-il si nous devons briser l'ordre d'exécution normal des instructions ? Utilisons des parenthèses. Dans cette notation, les instructions entre parenthèses sont exécutées en premier :

un = (b + c) * 10 ;

Ici, les valeurs des variables b et c seront d'abord ajoutées, puis la somme résultante sera multipliée par 10.

Les opérateurs entre parenthèses sont également soumis à la priorité. Par conséquent, plusieurs parenthèses imbriquées sont souvent utilisées :

un = ((b + c) * 10 - d) / 2 + 9 ;

Ici, les instructions seront exécutées dans l'ordre suivant :

1. Additionnez b et c.

2. Multipliez le montant obtenu par 10.

3. Soustraire d du produit.

4. Divisez la différence par 2.

5. Ajout de 9 au quotient.

Si vous supprimez les crochets :

un = b + c * 10 - ré / 2 + 9 ;

alors l'ordre d'exécution des opérateurs sera le suivant :

1. Multipliez c et 10.

2. Divisez d par 2.

3. Additionner b et multiplier c et 10.

4. Soustraction de la somme résultante du quotient de la division d à 2.

5. Ajouter 9 à la différence résultante.

Il s'avère que le résultat est complètement différent, n'est-ce pas ?

Opérateur Type de renvoie une chaîne indiquant le type de l'opérande.

Syntaxe

L'opérande suit le type d'opérateur :

Type de opérande

Choix

opérande est une expression représentant l'objet ou la primitive dont le type doit être renvoyé.

La description

Le tableau suivant répertorie les valeurs de retour possibles de typeof . Informations Complémentaires sur les types et les primitives est sur la page.

Exemples

// Nombres typeof 37 === "nombre" ; typeof 3.14 === "nombre" ; typeof(42) === "nombre" ; typeof Math.LN2 === "nombre" ; typeof Infinity === "nombre" ; typeof NaN === "nombre" ; // même s'il s'agit du type "Pas-un-nombre" de Number(1) === "number" ; // n'utilisez jamais cette notation ! // Chaînes typeof "" === "string" ; typeof "bla" === "chaîne" ; typeof "1" === "chaîne" ; // notez que le nombre à l'intérieur de la chaîne est toujours de type string typeof (typeof 1) === "string"; // typeof retournera toujours une chaîne dans ce cas typeof String("abc") === "string"; // n'utilisez jamais cette notation ! // Booléens typeof true === "booléen" ; typeof false === "booléen" ; typeof Booléen(vrai) === "booléen" ; // n'utilisez jamais cette notation ! // Symbols typeof Symbol() === "symbol" typeof Symbol("foo") === "symbol" typeof Symbol.iterator === "symbol" // Undefined typeof undefined === "undefined"; typeof declareButUndefinedVariable === "undefined" ; typeofVariablenondéclarée === "undefined" ; // Type d'objets(a : 1) === "objet" ; // utilisez Array.isArray ou Object.prototype.toString.call // pour faire la distinction entre les objets normaux et les tableaux typeof === "object"; typeof new Date() === "objet" ; // Tout ce qui suit entraîne des erreurs et des problèmes. Ne pas utiliser! typeof new Boolean(true) === "object" ; typeof new Number(1) === "objet" ; typeof new String("abc") === "object" ; // Type de fonctions de fonction() () === "fonction" ; typeof classe C() === "fonction" ; typeof Math.sin === "fonction" ;

nul

// Cela a été défini depuis la naissance de JavaScript typeof null === "object";

Dans la première implémentation de JavaScript, les valeurs étaient représentées par une paire type de balise et valeur. Le type de balise pour les objets était 0. null était représenté comme un pointeur nul (0x00 sur la plupart des plates-formes). Par conséquent, le type de la balise pour null était null, donc la valeur de retour de typeof est fausse. ()

Un correctif a été proposé dans ECMAScript (via disable) mais a été rejeté. Cela se traduirait par typeof null === "null" .

Utilisation du nouvel opérateur

// Toutes les fonctions constructeur créées avec "new" seront de type "object" var str = new String("String"); var num = nouveau nombre (100); typeofstr; // Retourne le type "objet" de num ; // Renvoie "object" // Mais il y a une exception pour le constructeur Function var func = new Function(); type de fonction ; // Retourne "fonction"

Expressions régulières

Les expressions régulières appelées étaient un ajout non standard dans certains navigateurs.

Type de /s/ === "fonction" ; // Chrome 1-12 Non conforme ECMAScript 5.1 typeof /s/ === "object"; // Firefox 5+ est conforme à ECMAScript 5.1

Bugs liés aux zones mortes temporaires

Avant ECMAScript 2015, l'opérateur typeof était garanti de renvoyer une chaîne pour l'opérande avec lequel il était appelé. Cela a changé avec l'ajout de déclarations let et const de portée de bloc sans levage. Maintenant, si des variables sont déclarées avec let et const , et que typeof est appelé sur elles dans le bloc de déclaration de variable, mais avant la déclaration, alors une ReferenceError est levée. Le comportement est différent des variables non déclarées, pour lesquelles typeof renverra "undefined". Les variables à portée de bloc se trouvent dans une "zone morte temporaire", qui dure du début du bloc jusqu'au moment où les variables sont déclarées. Dans cette zone, une tentative d'accès aux variables lève une exception.

Type de variable non déclarée === "non défini" ; type de newLetVariable ; let newLetVariable ; // ReferenceError typeof newConstVariable ; const newConstVariable = "bonjour" ; // Erreur de référence

Exceptions

Dans tous les navigateurs actuels, il existe un objet hôte document.all non standard, qui est de type Undefined.

Type de document.all === "undefined" ;

Bien que la spécification autorise les noms de type personnalisés pour les objets exotiques non standard, ces noms doivent être différents de ceux prédéfinis. La situation où document.all est de type undefined doit être considérée comme une violation exceptionnelle des règles.

Caractéristiques

spécification Statut commentaires
Dernier projet ECMAScript (ECMA-262)
Brouillon
ECMAScript 2015 (6e édition, ECMA-262)
Définition de "Le type d'Opérateur" dans cette spécification.
Standard
ECMAScript 5.1 (ECMA-262)
Définition de "Le type d'Opérateur" dans cette spécification.
Standard
ECMAScript 3e édition (ECMA-262)
Définition de "Le type d'Opérateur" dans cette spécification.
Standard
ECMAScript 1ère édition (ECMA-262)
Définition de "Le type d'Opérateur" dans cette spécification.
Standard Définition initiale. Implémenté en JavaScript 1.1

Compatibilité du navigateur

Mettre à jour les données de compatibilité sur GitHub

Des ordinateursMobileserveur
ChromebordFirefoxInternet ExplorerOpérasafarivue Web AndroidChrome pour AndroïdFirefox pour AndroïdOpéra pour AndroidSafari sur iOSInternet SamsungNode.js
Type deChrome Plein soutien 1 bord Plein soutien 12 Firefox Plein soutien 1 C'EST À DIRE Plein soutien 3 Opéra Plein soutien Ouisafari Plein soutien Ouivue web android Plein soutien 1 ChromeAndroid Plein soutien 18 FirefoxAndroid Plein soutien 4 OpéraAndroid Plein soutien OuiSafariiOS Plein soutien OuiSamsung Internet Androïd Plein soutien 1.0 nodejs Plein soutien Oui

Légende

Plein soutien Plein soutien

Remarques spécifiques à IE

Dans IE 6, 7 et 8, de nombreux objets hôtes sont des objets et non des fonctions. Par exemple.

  • indéfini indéfini"
  • Null : "objet"
  • Booléen : "booléen"
  • Numéro : "numéro"
  • Chaîne : "chaîne"
  • Fonction : "fonction"
  • Tout le reste : "objet"

Les remarques suivantes doivent être ajoutées à ce tableau :

1. typeof null === "objet" .

Théoriquement, il y a un point subtil ici. Dans les langages à typage statique, une variable de type objet ne peut pas contenir d'objet (NULL, nil, pointeur nul).

Pratiquement - en JavaScript, ce n'est pas pratique. Les développeurs d'ES 5.1 vont donc faire quelque chose de plus intuitif : typeof null === "null" .

Mais puisque nous sommes toujours autour de l'ES3, ne vous méprenez pas, par exemple, sur ceci :

/* La fonction recherche un objet et le renvoie ou null si rien n'est trouvé */ function search() () var obj = search(); if (typeof obj === "object") ( // avons-nous vraiment trouvé l'objet (FAIL) obj.method(); )

2. N'oubliez pas les objets wrapper (type de new Number(5) === "object").

3. Et n'oubliez pas le droit des navigateurs de faire n'importe quoi avec les objets hôtes.

Ne soyez pas surpris que Safari traite obstinément HTMLCollection comme un type de fonction, et IE antérieur au 9e conserve notre fonction alert() préférée comme un objet . De plus, Chrome considérait RegExp comme une fonction , mais maintenant il semble revenir à la raison et y répond avec un object .

toString()

Essayer de connaître le type d'une valeur à partir du résultat de sa méthode toString() est inutile. Dans toutes les "classes", cette méthode est redéfinie.

La méthode est bonne pour afficher des informations de débogage, mais le type de la variable ne peut pas être déterminé à partir de celle-ci.

Objet.prototype.toString()

Même si toString est remplacé dans des "classes" concrètes, nous avons toujours son implémentation d'origine à partir d'Object. Essayons de l'utiliser :

console.log ( Objet .prototype .toString .call (valeur) ) ;

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


Clinton dilue ce fardeau

Curieusement, cette méthode fonctionne étonnamment bien.

Pour les types scalaires, renvoie , , , .

Le plus drôle est que même new Number(5) sur lequel typeof a échoué ici renvoie .

Sur null et undefined la méthode échouera. Différents navigateurs renvoient attendu et , ou , ou même . Cependant, il est facile de déterminer le type de ces deux valeurs sans cela.

Les choses intéressantes commencent lorsque nous arrivons aux objets (ceux avec typeof === "object").

les objets intégrés fonctionnent, pratiquement, avec un bang :

  • {} —
  • Date-
  • Erreur-
  • regexp-

La seule chose qui sort de la liste des arguments, qui est soit , soit .
Avec les objets hôtes, tout est encore pire.

Dans IE, les objets DOM n'ont commencé à devenir des objets "normaux" qu'à partir de la 8e version, puis pas tout à fait jusqu'à la fin. Par conséquent, dans IE 6-8, tous ces objets (HTMLCOllection, DOMElement, TextNode , ainsi que document et window) sont simplement convertis en .

Dans tous les autres navigateurs (y compris IE9), vous pouvez déjà faire quelque chose avec le résultat toString. Même si tout n'est pas facile non plus : HTMLCollection là , puis . fenêtre - puis , puis , puis . Mais vous pouvez déjà essayer d'en tirer quelque chose.

C'est plus difficile avec DOMElement : il s'affiche sous la forme , un format différent pour chaque tag. Mais ici la saison régulière va nous aider.

Avec d'autres objets hôtes (dans les tests de localisation et de navigation), l'histoire est à peu près la même. Partout sauf IE, ils peuvent être identifiés par une chaîne.

Parmi les inconvénients de l'utilisation de Object.prototype.toString() :

1. Cette possibilité n'est pas consacrée par la norme. Et ici, nous devrions plutôt nous réjouir que tout fonctionne si bien, et non nous lamenter sur certains défauts.

2. Déterminer un type en analysant une chaîne renvoyée par une méthode qui n'est pas du tout destinée à déterminer le type, et même appelée sur un objet auquel elle ne s'applique pas, laisse des sédiments sur l'âme.

3. Dans l'ancien IE, comme vous pouvez le voir, les objets hôtes ne sont normalement pas identifiés.

Cependant, c'est tout à fait une chose de travail lorsqu'il est utilisé en conjonction avec d'autres outils.


Constructeurs

Et enfin, les constructeurs. Qui de mieux à dire sur la "classe" d'un objet en JS que son constructeur ?

null et undefined n'ont ni objets wrapper ni constructeurs.

Les autres types scalaires ont des wrappers, vous pouvez donc obtenir un constructeur :

(5) .constructeur === Nombre ; (Nombre .NaN ) .constructor === Nombre ; (true ) .constructor === booléen ; ("chaîne") .constructor === Chaîne ;

(5).constructeur === Nombre ; (Nombre.NaN).constructeur === Nombre ; (true).constructor === booléen ; ("string").constructor === String;

Mais instanceof ne fonctionnera pas ici :

5 instanceofNumber ; // faux Nombre .NaN instanceof Nombre ; // false true instanceof Boolean ; // false "string" instanceof String ; // faux

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

(instanceof fonctionnera pour le nouveau numéro (5) qui souffre depuis longtemps)

Avec les fonctions (qui sont aussi des objets), instanceof fera :

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

console.log((fonction () ()) instanceof Function); // vrai console.log((fonction () ()).constructeur === Fonction); // vrai

Tous les objets des classes intégrées sont également facilement identifiables par les constructeurs : Array , Date , RegExp , Error .

Un problème se pose ici avec les arguments dont le constructeur est Object .

Et le second avec l'objet lui-même, ou plutôt, comment y faire référence un objet créé via un constructeur personnalisé.

Seul l'objet de base peut être défini comme ceci :

obj instanceofObject;

Comme l'une des options de définition, itérer sur tous les autres types possibles (Array , Error ...) et si aucun d'entre eux ne relève de - "object".

Constructeurs et objets hôtes

Les choses empirent avec les objets hôtes.

Commençons par le fait qu'IE jusqu'à la 7e version incluse ne les considère pas du tout comme des objets normaux. Ils n'ont tout simplement pas de constructeurs et de prototypes là-bas (de toute façon, le programmeur ne peut pas les atteindre).

Les choses sont meilleures dans d'autres navigateurs. Il existe des constructeurs et vous pouvez déterminer la classe de valeur à partir d'eux. Ils ne s'appellent que différents navigateurs différemment. Par exemple, pour une HTMLCollection, le constructeur sera soit une HTMLCollection, soit une NodeList , soit même une NodeListConstructor .

Vous devez également définir un constructeur de base pour DOMElement. Dans FF, il s'agit, par exemple, de HTMLElement , dont HTMLDivElement et d'autres héritent déjà.

L'astuce est lancée par FireFox sous la version 10 et Opera sous la version 11. Là, le constructeur de la collection est Object .

constructeur.nom

Les constructeurs ont également une propriété name qui peut être utile.

Il contient le nom de la fonction constructeur, par exemple, (5).constructor.name === "Number" .

Cependant:
1. Dans IE ce n'est pas du tout, même dans le 9ème.
2. Dans les objets hôtes, les navigateurs façonnent à nouveau tout ce qui est beaucoup (et souvent ils n'ont pas du tout cette propriété). Dans Opera, DOMElement a un nom de constructeur en général Function.prototype .
3. arguments à nouveau " objet ".

conclusions

Aucune des méthodes présentées ne donne une définition à 100% du type/classe de la valeur dans tous les navigateurs. Cependant, ensemble, ils vous permettent de le faire.

Dans un avenir proche, j'essaierai de rassembler toutes les données dans des tableaux et de donner un exemple de fonction de définition.