JavaScript est souvent appelé le langage le plus simple pour les débutants, dans la programmation qui est la plus difficile à maîtriser. L'auteur du matériel, dont nous publions la traduction, déclare qu'il ne peut qu'être d'accord avec cette déclaration. Le fait est que JS est un langage vraiment ancien et vraiment flexible. Il est plein de constructions syntaxiques mystérieuses et de fonctionnalités obsolètes qu'il prend toujours en charge.

Aujourd'hui, nous allons parler des fonctionnalités et des options JavaScript peu connues pour leur application pratique.
JavaScript est toujours quelque chose de nouveau
Je travaille avec JavaScript depuis de nombreuses années et je rencontre constamment quelque chose que je n'aurais jamais soupçonné d'exister. Ici, j'ai essayé d'énumérer des fonctionnalités similaires peu connues du langage. En mode strict, certains d'entre eux ne fonctionneront pas, mais en mode normal, ce sont des exemples de code JS complètement corrects. Il convient de noter que je ne prétends pas conseiller aux lecteurs de mettre tout cela en service. Bien que ce dont je vais vous parler vous semble très intéressant, vous pouvez commencer à utiliser tout cela si vous travaillez en équipe et, pour le moins, surprendre vos collègues.
→ Le code dont nous allons discuter
ici se trouve
ici.Veuillez noter que je n'ai pas inclus des choses comme l'augmentation des variables, les fermetures, les objets proxy, l'héritage du prototype, async / wait, les générateurs, etc. Bien que ces caractéristiques du langage puissent être attribuées à des difficultés de compréhension, elles ne sont pas bien connues.
Opérateur nul
JavaScript a un opérateur unary
void
. Vous pouvez l'avoir rencontré sous la forme de
void(0)
ou
void 0
. Son seul but est de calculer l'expression à sa droite et de la rendre
undefined
.
0
ici, il est utilisé simplement parce qu'il est habituel, bien que ce ne soit pas nécessaire, et ici vous pouvez utiliser n'importe quelle expression valide. Certes, cet opérateur retournera en tout cas
undefined
.
Pourquoi ajouter un mot-clé spécial à la langue qui sert à renvoyer
undefined
, si vous pouvez simplement utiliser la valeur standard
undefined
? N'est-ce pas, il y a une redondance?
Il s'est avéré qu'avant l'apparition de la norme ES5 dans la plupart des navigateurs, une valeur standard
undefined
pouvait se voir attribuer une nouvelle valeur. Supposons que vous puissiez exécuter cette commande avec succès:
undefined = "abc"
. Par conséquent, une valeur
undefined
peut ne pas être ce qu'elle devrait être. À cette époque, l'utilisation du
void
nous permettait d'assurer la confiance dans l'utilisation du réel
undefined
.
Les crochets lors de l'appel des constructeurs sont facultatifs
Les crochets ajoutés après le nom de la classe, en invoquant le constructeur, sont complètement facultatifs (sauf si le constructeur a besoin de passer des arguments).
Dans l'exemple suivant, la présence ou l'absence de parenthèses n'affecte pas le bon fonctionnement du programme.
Les supports ne peuvent pas être utilisés avec IIFE
La syntaxe IIFE m'a toujours paru étrange. Pourquoi y a-t-il tous ces supports?
Il s'est avéré que les crochets ne sont nécessaires que pour indiquer à l'analyseur JavaScript qu'un code est une expression fonctionnelle et non une tentative incorrecte de déclarer une fonction. La connaissance de ce fait nous permet de comprendre qu'il existe de nombreuses façons de se débarrasser des crochets dans lesquels IIFE est enfermé, et en même temps d'écrire du code de travail.
Ici, l'opérateur
void
indique à l'analyseur que le code qui le suit est une expression fonctionnelle. Cela permet de se débarrasser des crochets autour de la déclaration de fonction. Et d'ailleurs, ici, vous pouvez utiliser n'importe quel opérateur unaire (
void
,
+
,
!
,
-
, etc.) et le code continuera de fonctionner. N'est-ce pas merveilleux?
Cependant, si vous êtes un lecteur attentif, vous vous demandez peut-être que l'opérateur unaire affecte le résultat renvoyé par IIFE. En fait, c'est comme ça. Mais la bonne chose est que si vous avez besoin du résultat de IIFE, que vous, par exemple, stockez dans une variable, alors vous n'avez pas besoin de parenthèses autour de IIFE. Voici un exemple.
Les accolades autour du premier IIFE améliorent seulement la lisibilité du code sans affecter son fonctionnement.
Si vous voulez mieux comprendre l'IIFE, jetez un œil à
ce matériel.
Construction avec
Savez-vous que JavaScript possède une construction
with
qui prend en charge les blocs d'expression? Cela ressemble à ceci:
with (object) statement
La construction
with
ajoute toutes les propriétés de l'objet qui lui sont passées dans la chaîne de portée utilisée lors de l'exécution des commandes.
with
peut sembler un excellent outil. Il semble que ce soit encore mieux que les nouvelles fonctionnalités de JS pour
la déstructuration d'objets , mais en fait ce n'est pas le cas.
La construction
with
est obsolète et son utilisation n'est pas recommandée. En mode strict, son utilisation est interdite. Il s'avère que les blocs provoquent des problèmes de performances et de sécurité.
Constructeur de fonctions
L'utilisation du mot-clé
function
n'est pas le seul moyen de définir une nouvelle fonction. Vous pouvez définir des fonctions de manière dynamique à l'aide du constructeur
Function
et du
new
opérateur. Voici à quoi ça ressemble.
Le dernier argument passé au constructeur est une chaîne avec le code de fonction. Deux autres arguments sont des paramètres de fonction.
Il est intéressant de noter que le constructeur
Function
est le "parent" de tous les constructeurs en JavaScript. Même le constructeur
Object
est un constructeur
Function
. Et le constructeur natif de
Function
est également
Function
. Par conséquent, un appel du type
object.constructor.constructor...
effectué pour tout objet JS un nombre suffisant de fois renverra le constructeur
Function
en conséquence.
Propriétés des fonctionnalités
Nous savons tous que les fonctions en JavaScript sont des objets de première classe. Par conséquent, personne ne nous empêche d'ajouter de nouvelles propriétés aux fonctions. C'est parfaitement normal, mais rarement utilisé.
Quand cela peut-il être nécessaire?
En fait, il existe plusieurs situations dans lesquelles cette fonctionnalité peut être utile. Considérez-les.
▍ Caractéristiques personnalisées
Supposons que nous ayons une fonction
greet()
. Nous avons besoin qu'elle affiche différents messages de bienvenue en fonction des paramètres régionaux utilisés. Ces paramètres peuvent être stockés dans une variable externe à la fonction. De plus, la fonction peut avoir une propriété qui définit ces paramètres, en particulier les paramètres de langue de l'utilisateur. Nous utiliserons la deuxième approche.
▍Fonctions avec variables statiques
Voici un autre exemple similaire. Supposons que nous ayons besoin d'implémenter un certain générateur qui produit une séquence de nombres ordonnés. Habituellement, dans de telles situations, afin de stocker des informations sur le dernier nombre généré, des variables de compteur statiques dans les classes ou IIFE sont utilisées. Avec cette approche, nous limitons l'accès au compteur et évitons la pollution du périmètre global avec des variables supplémentaires.
Mais que faire si nous avons besoin de flexibilité, si nous devons lire ou même modifier la valeur d'un tel compteur et ne pas obstruer la portée mondiale?
Bien sûr, vous pouvez créer une classe avec la variable correspondante et avec des méthodes qui vous permettent de travailler avec elle. Ou vous ne pouvez pas vous embêter avec de telles choses et simplement utiliser les propriétés des fonctions.
Propriétés de l'objet Arguments
Je suis sûr que la plupart d'entre vous savent que les fonctions ont un objet
arguments
. Il s'agit d'un objet de type tableau accessible dans toutes les fonctions (à l'exception des fonctions fléchées, qui n'ont pas leur propre objet
arguments
). Il contient une liste d'arguments passés à la fonction lors de son appel. De plus, il possède des propriétés intéressantes:
arguments.callee
contient un lien vers la fonction actuelle.arguments.caller
contient une référence à la fonction qui a appelé la fonction actuelle.
Prenons un exemple.
La norme ES5 interdit l'utilisation des propriétés de l'
caller
et de l'
caller
en mode strict, mais elles sont encore largement présentes dans de nombreux textes de programme compilés par JavaScript, par exemple dans les bibliothèques. Par conséquent, il est utile de les connaître.
Littéraux de modèle balisés
Certes, si vous avez quelque chose à voir avec la programmation JavaScript, vous avez entendu parler des
littéraux de
modèle . Les littéraux de modèle sont l'une des nombreuses grandes innovations de la norme ES6. Cependant, connaissez-vous les littéraux de modèles balisés?
Les littéraux de modèle balisés permettent au développeur de contrôler la façon dont le littéral de modèle se transforme en chaîne. Cela se fait à l'aide de balises spéciales. Une balise n'est que le nom d'une fonction d'analyseur qui reçoit un tableau de chaînes et de valeurs interprétées par un modèle de chaîne. Lorsque vous utilisez une fonction de balise, il est prévu qu'elle renvoie la chaîne terminée.
Dans l'exemple suivant, notre balise,
highlight
, interprète les données d'un modèle littéral et incorpore ces données dans une ligne finie, en les plaçant dans la balise HTML
<mark>
pour la sélectionner lorsqu'un tel texte est affiché sur une page Web.
Des façons intéressantes d'utiliser cette fonctionnalité peuvent être trouvées dans de nombreuses bibliothèques. Voici quelques exemples:
- composants de style - pour une utilisation dans les applications React.
- es2015-i18n-tag - pour la traduction et l'internationalisation de projets.
- craie - pour la sortie de messages multicolores sur la console.
Getters and Setters dans ES5
Les objets JavaScript, pour la plupart, sont assez simples. Supposons que nous ayons un objet
user
et que nous essayions d'accéder à sa propriété
age
à l'aide de la construction
user.age
. Avec cette approche, si cette propriété est définie, nous obtiendrons sa valeur, et si elle n'est pas définie, nous obtiendrons
undefined
. Tout est très simple.
Mais travailler avec des propriétés ne doit pas du tout être aussi primitif. Les objets JS implémentent le concept de getters et setters. Au lieu de renvoyer directement la valeur d'une propriété de l'objet, nous pouvons écrire notre propre fonction getter, qui retourne ce que nous considérons nécessaire. La même chose s'applique à l'écriture de nouvelles valeurs dans les propriétés à l'aide des fonctions de définition.
Les getters et setters vous permettent d'implémenter des schémas avancés pour travailler avec les propriétés. Lors de la lecture ou de l'écriture de propriétés, vous pouvez utiliser les concepts de champs virtuels, vous pouvez vérifier les valeurs des champs et lors de l'écriture ou de la lecture, certains effets secondaires utiles peuvent se produire.
Les getters et setters ne sont pas des innovations standard ES5. Ils étaient toujours présents dans la langue. Dans ES5, seuls des outils de syntaxe pratiques ont été ajoutés pour fonctionner avec eux. Les détails sur les getters et setters peuvent être trouvés
ici .
La bibliothèque populaire Node.js
Colors est un exemple d'utilisation des getters.
Cette bibliothèque
étend la classe String et y ajoute de nombreuses méthodes getter. Cela vous permet de convertir une chaîne dans sa version «colorée» afin que cette chaîne puisse ensuite être utilisée pour la journalisation. Cela se fait en travaillant avec les
propriétés de chaîne.
Opérateur virgule
JS a un opérateur virgule. Il vous permet d'écrire plusieurs expressions sur une seule ligne, séparées par une virgule, et de retourner le résultat de l'évaluation de la dernière expression. Voici à quoi ressemblent de tels designs.
let result = expression1, expression2,... expressionN
Ici, les valeurs de toutes les expressions seront calculées, après quoi la valeur de expressionN entrera dans la variable de
result
.
Il est possible que vous ayez déjà utilisé l'opérateur virgule dans
for
boucles.
for (var a = 0, b = 10; a <= 10; a++, b--)
Parfois, cet opérateur est très utile lorsque vous devez écrire plusieurs expressions sur la même ligne.
function getNextValue() { return counter++, console.log(counter), counter }
Il peut être utile lors de la conception de petites fonctions fléchées.
const getSquare = x => (console.log (x), x * x)
Opérateur Plus
Si vous devez rapidement transformer une chaîne en nombre, l'opérateur plus vous est utile. Il est capable de travailler avec une variété de nombres, et pas seulement, comme cela peut sembler, avec des nombres positifs. Nous parlons de nombres négatifs, octaux, hexadécimaux et de nombres en notation exponentielle. De plus, il est capable de convertir des objets
Date
et des objets de bibliothèque Moment.js en horodatages.
Double point d'exclamation
Il est à noter que ce qu'on appelle parfois «l'opérateur du double point d'exclamation» (Bang Bang ou Double Bang) n'est pas, en fait, un opérateur. Il s'agit d'un opérateur NOT logique ou d'un opérateur de négation logique qui ressemble à un point d'exclamation répété deux fois. Le point d'exclamation double est bon car il vous permet de convertir n'importe quelle expression en valeur booléenne. Si l'expression, du point de vue de JS, est vraie - après l'avoir traitée avec un double point d'exclamation,
true
sera renvoyée. Sinon,
false
sera retourné.
Opérateur de négation au niveau du bit
Avouons-le: personne ne se soucie des opérateurs au niveau du bit. Je ne parle pas de les utiliser. Cependant, l'opérateur de négation au niveau du bit peut être utilisé dans de nombreuses situations.
Lorsque cet opérateur est appliqué aux nombres, il les convertit comme suit: à partir du nombre
N
s'avère
-(N+1)
. Une telle expression donne
0
si
N
est
-1
.
Cette fonctionnalité peut être utilisée avec la méthode
indexOf()
lorsqu'elle est utilisée pour vérifier l'existence d'un élément dans un tableau ou dans une chaîne, car cette méthode, ne trouvant pas l'élément, renvoie
-1
.
Il convient de noter que dans les normes ES6 et ES7, respectivement, pour les chaînes et les tableaux, la méthode
includes()
est apparue. C'est certainement beaucoup plus pratique pour déterminer la présence d'éléments que d'utiliser l'opérateur de négation au niveau du bit et
indexOf()
.
Blocs nommés
JavaScript a un concept d'étiquettes, à l'aide duquel vous pouvez attribuer des noms (étiquettes) aux boucles. Vous pouvez ensuite utiliser ces étiquettes pour faire référence à la boucle appropriée lorsque vous appliquez des instructions
break
ou
continue
. Les étiquettes peuvent également être affectées à des blocs de code standard.
Les boucles étiquetées sont utiles lorsque vous travaillez avec des boucles imbriquées. Mais ils peuvent également être utilisés pour organiser facilement le code en blocs ou lors de la création de blocs dans lesquels le code peut être interrompu.
Notez que, contrairement à certaines autres langues, il n'y a aucune
goto
dans JS. Par conséquent, les étiquettes sont utilisées uniquement avec les instructions
break
et
continue
.
Résumé
Dans cet article, nous avons parlé de fonctionnalités JavaScript peu connues, dont la connaissance est utile à tout programmeur JS, au moins pour être prêt à rencontrer quelque chose d'inhabituel dans le code de quelqu'un d'autre. Si le sujet de «JS inconnu» vous intéresse, vous pouvez jeter un œil à
notre publication.
Chers lecteurs! Si vous connaissez des fonctionnalités peu connues de JS et voyez des options pour leur application pratique, veuillez nous en parler.
