Syntaxe JavaScript
# Syntaxe JavaScript

La syntaxe JavaScript est un ensemble de règles qui définissent ce qui constitue un programme valide en langage JavaScript.

## Origine

Brendan Eich a résumé ainsi le lignage de la syntaxe dans le premier paragraphe JavaScript 1.1 des spécifications : « JavaScript emprunte la plupart de sa syntaxe à Java, mais hérite aussi d'Awk et Perl, avec une influence indirecte de Self pour son système de prototype objet. »

## Variables

Les variables en JavaScript n'ont pas de type défini, et n'importe quelle valeur peut être stockée dans n'importe quelle variable. Les variables peuvent être déclarées avec const ou let. La différence entre ces deux mots clés est que les variables déclarées avec const ne peuvent être réaffectés alors qu'avec let si. Ces variables ont une portée au niveau du bloc de code où elles ont été déclarées.

Le mot clé var est une vieille syntaxe pour déclarer des variables qui ne doit plus être utilisée.

Voici un exemple de déclaration de variables :

## Types de données de base

### Nombres

Les nombres en JavaScript sont représentés en binaire comme des IEEE-754 Doubles, ce qui permet une précision de 14 à 15 chiffres significatifs JavaScript FAQ 4.2 (en). Comme ce sont des nombres binaires, ils ne représentent pas toujours exactement les nombres décimaux, en particulier les fractions.

Ceci pose problème quand on formate des nombres pour les afficher car JavaScript n'a pas de méthode native pour le faire. Par exemple:

En conséquence, l'arrondi devrait être utilisé dès qu'un nombre est formaté pour l'affichage (en). La méthode toFixed ne fait pas partie des spécifications de l'ECMAScript et est implémentée différemment selon l'environnement, elle ne peut donc être invoquée.

Les nombres peuvent être spécifiés dans l'une de ces notations :

Dans certaines implémentations de l'ECMAScript comme l'ActionScript, les couleurs sont parfois spécifiées avec des nombres entiers en écriture hexadécimale :

Le constructeur Number peut être utilisé pour réaliser une conversion numérique explicite :

Quand il est utilisé comme un constructeur, un objet wrapper numérique est créé (toutefois il est peu employé) :

### Tableaux

Un tableau est un ensemble d'éléments repérés par leur indice, qui est un nombre entier. En JavaScript, tous les objets peuvent être formés d'un ensemble d'éléments, mais les tableaux sont des objets spéciaux qui disposent de méthodes spécifiques (par exemple, join, slice, et push).

Les tableaux ont une propriété length qui représente la longueur du tableau, c'est-à-dire le nombre d'éléments qu'il peut contenir. La propriété length d'un tableau est toujours supérieure à l'indice maximal utilisé dans ce tableau (N.B. Les indices de tableaux sont numérotés à partir de zéro). Si on crée un élément de tableau avec un indice supérieur à length, length est automatiquement augmentée. Inversement, si on diminue la valeur de length, cela supprime automatiquement les éléments qui ont un indice supérieur ou égal. La propriété length est la seule caractéristique qui distingue les tableaux des autres objets.

Les éléments de tableau peuvent être accédés avec la notation normale d'accès aux propriétés d'objet :

Les 2 notations ci-dessus sont équivalentes.

Par contre, il n'est pas possible d'utiliser la notation "point" : objet.propriété, ni d'autres représentations du nombre entier de l'indice :

La déclaration d'un tableau peut se faire littéralement ou par l'utilisation du constructeur Array :

Les tableaux sont implémentés de façon que seuls les éléments utilisés utilisent de la mémoire ; ce sont des tableaux sporadiques. Si l'on crée un tableau monTableau de longueur 58, puis qu'on attribue monTableau[10] = 'uneValeur' et monTableau[57] = 'uneAutreValeur', l'espace occupé correspondra seulement à ces 2 éléments, comme pour tous les objets. La propriété length du tableau restera quand même à 58.

Grâce à la déclaration littérale, on peut créer des objets similaires aux tableaux associatifs d'autres langages :

On peut mélanger les déclarations littérales d'objets et de tableaux pour créer facilement des tableaux associatifs, multidimensionnels, ou les deux à la fois :

### Chaînes de caractères

En Javascript la chaîne de caractères est considérée comme une suite de caractères. Une chaîne de caractères en JavaScript peut être directement créée en plaçant des caractères entre apostrophes (doubles ou simples) :

Les caractères d'une chaîne peuvent être accédés individuellement (ils sont considérés comme des chaînes d'un seul caractère) avec la même notation que pour les tableaux :

En JavaScript les chaînes sont immuables :

L'opérateur d'égalité == permet de comparer le contenu de deux chaînes de caractères (en tenant compte de la casse), et retourne un booléen :

## Opérateurs

L'opérateur '+' est surchargé ; il est utilisé pour la concaténation de chaîne de caractères et l'addition ainsi que la conversion de chaînes de caractères en nombres.

### Arithmétiques

Opérateurs binaires

Opérateurs unaires

### Booléens

Le langage Javascript possède 3 opérateurs booléens :

Dans une opération booléenne, toutes les valeurs sont évaluées à true (VRAI), à l'exception de :

* la valeur booléenne false (FAUX) elle-même
* le nombre 0
* une chaîne de caractères de longueur 0
* une des valeurs suivantes : null undefined NaN

On peut faire explicitement la conversion d'une valeur quelconque en valeur booléenne par la fonction Boolean :

L'opérateur booléen unaire NOT ! évalue d'abord la valeur booléenne de son opérande, puis rend la valeur booléenne opposée :

En doublant l'opérateur !, on peut normaliser une valeur booléenne :

Dans les premières implémentations de Javascript et JScript, les opérateurs booléens && et || fonctionnaient comme leurs homologues dans d'autres langages issus du C, c'est-à-dire qu'ils rendaient toujours une valeur booléenne :

Dans les implantations récentes, les opérateurs booléens && et || rendent un de leurs deux opérandes :

Ce fonctionnement provient du fait que l'évaluation s'effectue de gauche à droite. Dès que la réponse est déterminée, l'évaluation s'arrête :

* x && y est nécessairement FAUX si x est FAUX, ce n'est pas la peine d'évaluer y
* x || y est nécessairement VRAI si x est VRAI, ce n'est pas la peine d'évaluer y

Ce nouveau comportement est peu connu, même parmi les développeurs Javascript expérimentés, et peut causer des problèmes si on s'attend à recevoir une valeur booléenne.

### Binaires

Opérateurs binaires

Opérateur unaire

Affectation

## Structures de contrôle

### Si Sinon

Dans chaque structure if..else, la branche else :

* est facultative
* peut contenir une autre structure if..else

### Opérateur conditionnel

L'opérateur conditionnel crée une expression qui, en fonction d'une condition donnée, prend la valeur de l'une ou l'autre de 2 expressions données. Son fonctionnement est similaire à celui de la structure si..sinon qui, en fonction d'une condition donnée, exécute l'une ou l'autre de 2 instructions données. En ce sens on peut dire que l'opérateur conditionnel est aux expressions ce que la structure si..sinon est aux instructions.

Le code ci-dessus, qui utilise l'opérateur conditionnel, a le même effet que le code ci-dessous, qui utilise une structure si..sinon :

Contrairement à la structure si..sinon, la partie correspondant à la branche sinon est obligatoire.

### Instruction switch

L'instruction switch remplace une série de si..sinon pour tester les nombreuses valeurs que peut prendre une expression :

* l'instruction break; termine le bloc case (le cas à traiter). Elle est facultative dans la syntaxe Javascript. Cependant, elle est recommandée, car en son absence l'exécution continuerait dans le bloc case suivant. Dans le dernier bloc case d'un switch l'instruction break; ne sert à rien, sauf à prévoir l'éventualité où on rajouterait plus tard un bloc case supplémentaire.
* la valeur du case peut être une chaîne de caractères
* les accolades { } sont obligatoires

### Boucle For

Syntaxe pour plusieurs lignes d'instructions :

Syntaxe pour une seule instruction :

### Boucle For..in

* L'itération s'effectue sur toutes les propriétés qui peuvent être associées à un compteur
* Cette boucle peut aussi être utilisée avec un tableau.
* L'ensemble des propriétés balayées dans la boucle diffère selon les navigateurs. Théoriquement, cela dépend d'une propriété interne appelée "DontEnum" définie dans le standard ECMAscript, mais dans la pratique chaque navigateur renvoie un ensemble différent.

### Break, continue et label

break permet de sortir d'une boucle.

continue permet de passer à l'itération suivante de la boucle.

Les labels permettent de "briser" (break) ou continuer (continue) plusieurs niveaux de boucles.

Les labels permettent aussi de sortir d'un block de code anonyme.

## Fonctions

Une fonction est un bloc d'instructions avec une liste de paramètres (éventuellement vide). Elle possède généralement un nom et peut renvoyer une valeur.

Syntaxe pour l'appel d'une fonction anonyme, c'est-à-dire sans nom :

Exemple de fonction : l'algorithme d'Euclide. Il permet de trouver le plus grand commun diviseur de deux nombres, à l'aide d'une solution géométrique qui soustrait le segment le plus court du plus long :

* le nombre des paramètres passés à l'appel de la fonction n'est pas obligatoirement égal au nombre des paramètres nommés dans la définition de la fonction
* si un paramètre nommé dans la définition de la fonction n'a pas de paramètre correspondant dans l'appel de la fonction, il reçoit la valeur undefined
* à l'intérieur de la fonction, les paramètres peuvent être accédés par l'objet arguments. Cet objet donne accès à tous les paramètres en utilisant un indice : arguments[0], arguments[1], ... arguments[n], y compris ceux qui sont au-delà des paramètres nommés. Attention, arguments n'est pas un tableau. Il a une propriété length mais il n'a pas les méthodes des tableaux comme slice, sort, etc.
* tous les paramètres sont passés par valeur, sauf pour les objets les tableaux et les fonctions qui sont passés par référence.

Il est toutefois possible de transformer l'objet arguments en un tableau grâce à :

On peut déclarer une fonction à l'intérieur d'une autre. La fonction ainsi créée pourra accéder aux variables locales de la fonction dans laquelle elle a été définie. Elle se souviendra de ces variables, même après que l'on sera sorti de la fonction dans laquelle elle a été définie, ce qui constitue une fermeture.

## Objets

Par commodité, on sépare habituellement les types de données en primitives (ou types de données de base) et objets. Les objets sont des entités qui ont une identité (ils ne sont égaux qu'à eux-mêmes) et qui associent des noms de propriété à des valeurs. Les propriétés sont appelées slots dans le vocabulaire de la programmation orientée prototype.

Le langage Javascript propose divers types d'objets prédéfinis : tableau, booléen, date, fonction, maths, nombre, objet, expression régulière et chaîne de caractères. D'autres objets prédéfinis sont des objets hôte issus de l'environnement d'exécution. Par exemple dans un navigateur les objets hôtes appartiennent au modèle DOM : fenêtre, document, lien hypertexte, etc.

On peut voir les objets les plus simples comme des dictionnaires. En tant que dictionnaires, ils contiennent des couples clé-valeur, où la clé est une chaîne de caractères et la valeur peut être de n'importe quel type. Les objets simples sont souvent implémentés comme des dictionnaires. Cependant, les objets possèdent des fonctionnalités que n'ont pas les dictionnaires, comme une chaîne prototype.

Exemple de déclaration littérale d'un objet contenant des valeurs :

Les propriétés des objets peuvent être créées, lues et écrites, soit avec la notation "point" objet.propriété, soit avec la syntaxe utilisée pour les éléments de tableau :

### Création

Les objets peuvent être créés à l'aide d'un constructeur ou de façon littérale. Le constructeur peut utiliser la fonction prédéfinie Object ou une fonction sur mesure. Par convention les noms des fonctions constructeurs commencent par une majuscule.

Les déclarations littérales d'objets et de tableaux permettent de créer facilement des structures de données adaptées aux besoins :

C'est la base de JSON, un format d'échanges de données utilisant une syntaxe inspirée des objets Javascript.

### Constructeur

Les constructeurs assignent simplement des valeurs aux slots de l'objet nouvellement créé. Les valeurs assignées peuvent être elles-mêmes d'autres fonctions.

Contrairement à ce qui se passe dans d'autres langages à objets, en Javascript les objets n'ont pas de type. Le constructeur qui sert à créer l'objet n'est pas mémorisé. C'est simplement une fonction qui remplit les slots et le prototype du nouvel objet. Donc le constructeur ne correspond pas à la notion de classe qu'on trouve dans d'autres langages.

Les fonctions sont elles-mêmes des objets, ce qui peut servir à obtenir le même fonctionnement que les "static properties" des langages C++ et Java (cf exemple ci-dessous).

Les fonctions ont une propriété spécifique appelée prototype (cf paragraphe Héritage ci-dessous).

La destruction d'objet est rarement pratiquée car elle est peu nécessaire. En effet le ramasse-miettes détruit automatiquement les objets qui ne sont plus référencés.

Exemple : manipulation d'objet

### Méthodes

Une méthode est simplement une fonction qui est assignée à la valeur d'un slot d'objet. Contrairement à ce qui se passe dans de nombreux langages à objets, dans Javascript il n'y a pas de distinction entre la définition d'une fonction et la définition d'une méthode. La différence peut apparaître lors de l'appel de la fonction : une fonction peut être appelée comme une méthode.

Dans l'exemple ci-dessous, la fonction Gloup assigne simplement des valeurs aux slots. Certaines de ces valeurs sont des fonctions. De cette façon Gloup peut assigner des fonctions différentes au même slot de différentes instances du même objet. N.B. Il n'y a pas de prototypage dans cet exemple.

### Héritage

Javascript supporte les hiérarchies d'héritage par prototypage de la même façon que le langage self. Chaque objet contient un slot implicite appelé prototype.

Dans l'exemple ci-dessous, la classe Bagnole hérite de la classe Vehicule. Quand on crée l'instance b de la classe Bagnole, une référence à l'instance de base de la classe Vehicule est copiée dans b. La classe Bagnole ne contient pas de valeur pour la fonction roule. Quand la fonction roule est appelée cette fonction est recherchée dans l'arborescence d'héritage et elle est trouvée dans la classe Vehicule. Cela se voit clairement dans l'exemple : si on change la valeur de vehicule.roule, on retrouve cette valeur dans b.roule.

Les implémentations de Javascript basées sur Mozilla permettent d'accéder explicitement au prototype d'un objet grâce à un slot appelé _proto_ comme dans l'exemple ci-dessous.

L'exemple suivant montre clairement que les références aux prototypes sont copiées lors de la création de l'instance et que les changements appliqués au prototype se répercutent dans toutes les instances qui s'y réfèrent.

En pratique de nombreuses variations d'héritage sont utilisées, ce qui peut être très puissant mais aussi prêter à confusion.

## Exceptions

À partir de Internet Explorer 5 et Netscape 6, les implémentations de Javascript comportent une instruction try ... catch ... finally pour la gestion des exceptions, c'est-à-dire les erreurs en cours d'exécution. Cette instruction traite les exceptions provoquées par une erreur ou par une instruction de levée d'exception.

La syntaxe est la suivante :

D'abord, les instructions du bloc try s'exécutent.

* si pendant l'exécution du bloc try une exception est déclenchée, l'exécution passe au bloc catch et le code de l'exception est passé dans le paramètre. À la fin du bloc catch, l'exécution continue dans le bloc finally
* si aucune exception ne se déclenche, le bloc catch est ignoré et l'exécution passe au bloc finally

Le bloc finally sert souvent à libérer la mémoire, pour éviter qu'elle ne reste bloquée lors d'une erreur fatale, même si ce souci ne se pose guère dans Javascript.

Exemple :

Le bloc finally est facultatif :

Le bloc catch est lui aussi facultatif. Dans ce cas, si une exception se déclenche, l'exécution quitte le bloc try et passe au bloc finally sans que l'erreur soit traitée.

Attention : il est obligatoire d'avoir au moins l'un des deux blocs catch ou finally, ils ne peuvent pas être absents tous les deux.

Si vous utilisez le bloc catch, le paramètre est obligatoire, même si vous ne l'utilisez pas dans le bloc.

Sous Mozilla il est permis d'avoir plusieurs instructions catch. Il s'agit d'une extension au standard ECMAScript. Dans ce cas, la syntaxe est similaire à celle de Java :

## Divers

### Casse

Javascript est sensible à la casse.

L'usage est de donner aux objets un nom qui commence par une majuscule et de donner aux fonctions ou variables un nom qui commence par une minuscule.

### Espaces vides et points-virgules

Dans le langage Javascript les instructions se terminent par un point-virgule.

Cependant Javascript comporte un mécanisme d'insertion automatique de point-virgule : lors de l'analyse d'une ligne de code qui ne se termine pas par un point-virgule, si le contenu de la ligne correspond à une instruction correcte, la ligne peut être traitée comme si elle se terminait par un point-virgule.

Les caractères espace, tabulation, fin de ligne et leurs variantes, quand ils ne sont pas inclus dans une chaîne de caractères, sont désignés sous le terme général whitespace. Les caractères whitespace peuvent avoir un effet sur le code à cause du mécanisme d'insertion automatique de point-virgule.

Pour éviter les effets non désirés dus au mécanisme d'insertion automatique de point-virgule, il est conseillé d'ajouter systématiquement un point-virgule à la fin de chaque instruction, même si cela diminue la lisibilité du code.

Exemple d'effet non désiré :

Autre exemple :

D'autre part, les caractères whitespace accroissent inutilement la taille du programme et donc du fichier .js. La solution la plus simple à ce problème est de faire comprimer les fichiers par le serveur, ce qui réduira la taille de tous les fichiers source téléchargés sur le serveur. La compression en zip fonctionne mieux que les logiciels spécialisés en suppression de whitespace (whitespace parser).

### Commentaires

La syntaxe des commentaires est la même qu'en C++.

Il est interdit d'imbriquer les commentaires :

