Movatterモバイル変換


[0]ホーム

URL:


Aller au contenu
Wikilivres
Rechercher

Programmation JavaScript/Variables

Un livre de Wikilivres.
<Programmation JavaScript
Mots réservésMots réservés
OpérateursOpérateurs
  1. Introduction
    Programmer en deux minutes
  2. Outils de développement
  3. Syntaxe
    1. Ligne d'instruction
    2. Ordre d'évaluation
    3. Bloc d'instructions
    4. Identificateurs
    5. Expression littérale
    6. Commentaire
    7. Mots réservés
    8. Variables
    9. Opérateurs
    10. Structures de contrôle
    11. Exceptions et erreurs
    12. Fonctions utilisateur
    13. Évènement
  4. Objets prédéfinis
    1. window
    2. document
    3. navigator
    4. Array
    5. Boolean
    6. Date
    7. Error
    8. Function
    9. Math
    10. Number
    11. Object
    12. String
    13. Element
    14. RegExp
  5. Fonctions prédéfinies
  6. Programmation avancée
    1. Opérateurs de bits
    2. Fermeture
    3. Programmation objet
    4. Notation JSON
    5. AJAX
    6. Stockage
    7. Générateurs
    8. Interface DOM
    9. Objets Microsoft
  7. Frameworks
    1. Dojo
      Hello World
      Widgets
      Ressources
    2. jQuery
    3. Node.js
    4. React.js
  8. Bibliothèques
    1. Datatables
  9. Tests
    1. Ava
    2. Jest
    3. Cypress
  10. Débogage
  11. Erreurs connues
  12. Références

Mots réservésMots réservés
OpérateursOpérateurs

Les variables permettent d'instancier un objet et de manipuler cette instance à l'aide d'un identificateur (le nom de la variable). Tous les identificateurs en JavaScript sont des références à un objet. Javascript étant un langage au typage dynamique, le type des objets n'est pas déclaré explicitement et il peut changer automatiquement.

Typage dynamique

[modifier |modifier le wikicode]

Il est donc possible de déclarer une variable sans lui définir de type. Ou plutôt, une variable déclarée de telle manière sera du type undefined.
Tout au long de son utilisation, cette variable pourra changer de type sans que l'interpréteur n'y trouve rien à redire.

var ma_versatile; // est undefinedma_versatile = "Je deviens une chaîne"; // devient stringma_versatile = 5; // devient numberma_versatile = new Array(); // devient object

Il n'est en fait pas nécessaire de déclarer une variable (avec le mot-clévar). La différence est expliquée ci-après.

Identificateur

[modifier |modifier le wikicode]

Les règles d'élaboration des identificateurs sont décrites àce lien.Pour résumer, les identificateurs comportent des caractères alphanumériques et le tiret soulignant (_). Ils ne peuvent commencer par un chiffre, et les majuscules comptent.

Portée

[modifier |modifier le wikicode]

Propriétés

[modifier |modifier le wikicode]

L'instanciation directe (sans mot-clé var) d'un objet avec un identificateur donne souvent l'impression de créer une variable globale. En réalité, la notion de "variable globale" n'existe pas en JavaScript. Toutes les variables sont, sauf quand on les déclare avecvar, des propriétés d'un objet. Par défaut, cet objet est implicitement l'objetwindow (et non,window n'est pas une variable globale qui ferait exception à la règle car il est une de ses propres propriétés, c'est-à-dire quewindow est une propriété dewindow).

Commewindow reste l'objet implicite la plupart du temps, une variable créée ainsi pourra être employée comme si elle était globale :

ma_variable = "une valeur";function maFonction(){  mon_autre_variable = "une autre valeur"}maFonction()alert(mon_autre_variable) // affiche "une autre valeur"

La variable mon_autre_variable est certes déclarée dans une fonction, mais il faut lire "window.mon_autre_variable" donc c'est une propriété de window et elle ne sera pas détruite automatiquement à la fin de la fonction.

Sous-entendre un objet

[modifier |modifier le wikicode]

Pour économiser du code, il peut être intéressant de sous-entendre un autre objet quewindow. Cela se fait explicitement avec un blocwith. Cette déclaration ne fonctionne pas aussi simplement qu'en Basic, par exemple. L'objet est en fait placé en haut de lascope chain dans le bloc d'instruction, presque comme si ses propriétés étaient des variables locales d'une fonction (voirProgrammation JavaScript/Scope chain). Lorsqu'on utilise un identificateur dans un blocwith, la résolution se fait aussitôt qu'une des conditions suivantes est remplie :

  1. l'identificateur est une propriété existante de l'objet sous-entendu
  2. l'identificateur existe ailleurs dans lascope chain, en partant du haut (par exemple, une variable locale)
  3. l'identificateur est une propriété existante de window

Si aucune condition n'est remplie et que l'expression affecte une valeur à la variable, cette variable est créée comme propriété de l'objet global. Si l'expression ne fait qu'utiliser la valeur, elle retournera simplementundefined.

c=trued="propriété de window"monObjet={a:0,d:"propriété de monObjet"}with(monObjet){alert(a)// affiche la valeur de monObjet.a : "0"a=2// monObjet.a existe et va être utilisé// si on veut utiliser window.a, il faut le faire explicitementwindow.a=5b="texte"// b n'est encore défini nulle part donc window.b est créé// si on veut créer monObjet.b, il faut le faire explicitementmonObjet.b="autre chose"deletec// monObjet.c n'existe pas, mais window.c va être utiliséalert(d)// affiche "propriété de monObjet"// si on veut l'autre, il faut être explicitealert(window.d)// affiche "propriété de window"}

Variables locales

[modifier |modifier le wikicode]

À l'aide de la déclarationvar, il est possible de définir une variable locale, qui n'est pas une propriété d'un autre objet. Cette déclaration peut avoir lieu n'importe où dans le corps d'une fonction, pas nécessairement au début, mais seules les utilisation ultérieures de l'identificateur feront référence à la variable locale puisqu'elle n'existait pas avant.

Comme toute variable locale, elle est automatiquement détruite à la fin de la fonction, bien que sa valeur puisse être sauvegardée dans certains cas (voirFermeture).Par contre, elle ne peut pas être détruite par l'opérateurdelete.

functionfoo(){varloc_1=2// n'a pas d'existence en dehors de foo()for(i=0;i<loc_1;i++){varloc_2=2*loc_1;// loc_2 est disponible pour toute la fonction foo()alert(loc_2);}alert(loc_2);// S'affiche sans problème}alert(loc_2);// Provoque une erreur

Si la déclarationvar est utilisée en-dehors de toute fonction, la variable sera utilisable dans tout le script.

Hoisting

[modifier |modifier le wikicode]

L'exemple précédent montre l'effethositing (levage) des déclarations avec le mot-clévar.Les déclarations sont en effet remontées au niveau du premier bloc de code de la fonction.Cela permet dans l'exemple précédent de continuer à accéder à la variableloc_2 après la bouclefor.

Par contre, la partie initialisation n'est pas rehaussée et la variable a donc une valeur indéfinie (undefined).L'exemple précédent équivaut au code suivant :

functionfoo(){varloc_1;varloc_2;// Déclaration rehausséevari;// Déclaration impliciteloc_1=2;for(i=0;i<loc_1;i++){loc_2=2*loc_1;// loc_2 est disponible pour toute la fonction foo()alert(loc_2);}alert(loc_2);// S'affiche sans problème, vaudrait undefined si loc_1 <= 0}

Il en va de même pour les fonctions déclarées dans des fonctions :

functionadd(n){vart=addn(5);functionaddn(a)// ^^ déclaration rehaussée implicitement{returna+n;}returnt;}

Cela équivaut au code suivant :

functionadd(n){vart;functionaddn(a){returna+n;}t=addn(5);returnt;}

Depuis Javascript 5, le mot-clélet permet de déclarer des variables locales à un bloc, sans effet de rehaussement.

functionfoo(){letloc_1=2;for(i=0;i<loc_1;i++){letloc_2=2*loc_1;console.log(loc_2);}console.log(loc_2);// --> Uncaught ReferenceError: loc_2 is not defined}

Types

[modifier |modifier le wikicode]

Javascript est faiblement typé, mais typé quand même. Voici une revue des types que peut prendre une variable. Il est possible à tout moment de vérifier le type avec l'opérateurtypeof.

undefined

[modifier |modifier le wikicode]

Une variable est du type undefined dans trois cas:

  • Après déclarationvar sans affectation
varmaNouvelleVar;// Déclarée mais pas affectéealert(typeofmaNouvelleVar);// Affiche undefined
  • Si on lui affecte explicitement la valeurundefined, ou qu'on lui affecte le résultat d'une expression qui retourne cette valeur.
varjeSaisPas=undefinedvarcaNExistePas="impossible".enFrancaisalert(typeofjeSaisPas)// Affiche undefinedalert(typeofcaNExistePas)// Affiche undefined
  • Si elle n'a pas été déclarée ni utilisée, ou bien qu'elle a été effacée par l'opérateurdelete.
alert(typeofvarPasDeclaree);// Affiche undefined (si elle n'a effectivement pas été affectée)monEphemere="exister";deletemonEphemere;// la vie est courtealert(typeofmonEphemere);// Affiche undefinedalert(varPasDeclaree)// erreur !!

À noter : dans les deux premiers cas, la variable existe et possède une valeur (undefined). On peut lire cette valeur sans provoquer d'erreur. Dans le troisième cas cependant, la variable n'existe pas : l'opérateurtypeof retourne "undefined", mais lire directement la valeur de la variable provoque une erreur.

number

[modifier |modifier le wikicode]

JavaScript réunit en un seul type les entiers, petits et grands, les décimaux, et les réels, flottants ou pas.

r=1/3;alert(r);// affiche 0.333333333333alert(typeofr);// affiche numbern=4/2;alert(n);// affiche 2alert(typeofn);// affiche number3.6e5// 360 000 en notation scientifique0x40// 64 en notation hexadécimale0100// 64 en notation octale

Concrètement, les nombres sont stockés sur 64 bits, avec une mantisse de 53 bits. Cela permet des valeurs entières jusqu'à 9 007 199 254 740 991, à partir duquel on commence à perdre de la précision jusqu'à 2^1024-1 qui est la valeur flottante la plus élevée représentable en JavaScript.

En fait, JavaScript inclut également dans le typenumber deux valeurs spéciales.Infinity, un nombre signé, est renvoyé dès que le résultat dépasse la capacité de stockage denumber, mais aussi dans des cas limites simples. Dans les cas indécidables, ou bien lorsqu'une opération qui retourne un nombre ne peut pas le faire, c'est la valeurNaN (Not A Number) qui est renvoyée (voir lesopérateurs arithmétiques,les méthodes de Number etles méthodes de Math pour les cas qui produisent ces deux valeurs).

1/0==Infinity-2/Infinity==00/0==NaNNumber("texte")==NaN

string

[modifier |modifier le wikicode]

Le typestring stocke une chaîne de caractères. C'est aussi le type le plus "faible" du langage : n'importe quelle valeur peut être convertie en chaîne, et en cas de doute avec l'opérateur+, c'est une concaténation qui aura lieu, pas une addition.

s = "Une chaîne de caractères";alert(typeof s); // Affiche "string"

Tous les objets possèdent une méthode générique toString() "magique" qui est appelée lorsqu'il faut convertir leur valeur en chaîne. Elle peut bien sûr être écrasée par une méthode plus spécifique.

Les chaînes de caractères en JavaScript sont encadrées par des guillemets droits (double quotes, ") ou dessingle quotes ('), au choix. Il n'y a pas de distinction entre des chaînes définies avec l'un ou l'autre, mais si on commence une chaîne par un type de guillemet il faut la finir par le même type. À l'intérieur d'une chaîne, les séquences d'échappement connues fonctionnent comme partout :

  • \n :line feed, saut de ligne Unix
  • \r :carriage return, saut de ligne Mac OS classique
  • \t : tabulation
  • \\ :backslash
  • \' ou \" : un guillemet si la chaîne commence par ce caractère

etc.

Enfin, JavaScript utilise des chaînes de caractères Unicode multi-octets. Quel que soit l'encodage du fichier où est écrit le script, il est toujours possible d'inclure n'importe quel caractère dans une chaîne, soit en récupérant une chaîne d'un autre fichier, soit en créant une chaîne avec la méthode statique String.fromCharCode(), soit en utilisant la séquence d'échappement :

  • \xHH : HH est le code hexadécimal du caractère dans l'encodage courant
  • \uHHHH : HHHH est le code hexadécimal du caractère dans le tableau Unicode. Il ne peut y avoir moins de 4 chiffres après la séquence \u.

boolean

[modifier |modifier le wikicode]

Une variable de type boolean accepte deux valeurs : vrai et faux.

b=true;alert(typeofb);// Affiche "boolean"c=(5==3);// est faux, mais l'expression est booléenne.alert(typeofc);// Affiche "boolean"

Dans une comparaison, les valeurs suivantes sont équivalentes (opérateur==) àfalse :

  • 0 : le nombre zéro et ses variations, du style 0.000, 0x0, 0e12, etc.
  • "" : la chaîne vide
  • "0" : la chaîne contenant le nombre zéro, et toutes ses variations, comme pour le nombre
  • [] ounewArray() : un tableau vide, et en fait tout objet dont la conversion en chaîne est l'une des valeurs ci-dessus

Par ailleurs, les valeurs suivantes donnentfalse si on les convertit (explicitement ou pas) en booléen, bien qu'elle ne soient pas toutes équivalentes par comparaison :

  • 0 et ses variations
  • ""
  • null
  • NaN
  • undefined

Comme ces listes le montrent, une valeur peut être équivalente àfalse sans être considérée comme fausse elle-même ! Et inversement, une valeur considérée comme fausse n'est pas forcément équivalente au booléenfalse.

Cela peut sembler surprenant et illogique à première vue (et source de quelques bugs) mais il faut comprendre l'origine de ces différences :

  • les valeursnull,NaN etundefined refusent simplement d'être équivalentes à n'importe quoi sauf elles-mêmes. Donc l'opérateur== retournera systématiquementfalse si une des opérandes estnull,NaN ouundefined et que l'autre n'est pas strictement identique. Cependant, à choisir entre vrai ou faux (lors d'une conversion enBoolean, il n'y a pas d'autre choix), ces valeurs sont plutôtfalse.
  • les chaînes "0" et ses variantes sont... des chaînes, etfalse est un booléen. JavaScript ne peut pas comparer directement deux types différents. Il pourrait convertir la chaîne en booléen, mais préfère convertir les deux ennumber (le typenumber est plus "fort"). Le résultat est 0 == 0 la comparaison est donc vraie. Cependant, "0" reste une chaîne non-vide, et si on la convertir en booléen, on obtienttrue.
  • la chaîne "false" est aussi une chaîne, mais ne peut pas être convertie ennumber. JavaScript, en dernier recours, convertit alors l'autre opérande enstring et se retrouve à comparer "false"=="false", ce qui est vrai. Par contre, comme pour "0", la chaîne n'est pas vide et sa conversion en booléen donnetrue.
  • le tableau vide [] est un tableau, donc JavaScript le convertit en chaîne pour le comparer àfalse. Or, la méthode toString() d'un tableau retourne la fusion de tous les éléments, séparés par des virgules. Comme il n'y a aucun élément dans le tableau, le résultat est la chaîne vide "", qui est équivalente àfalse. Par contre, un tableau est de type objet et sa conversion en booléen donnetrue.

Une valeur qui n'est pas équivalente àfalse ne sera pas pour autant équivalente àtrue par comparaison, à commencer parnull,NaN etundefined mais aussi toute valeur qui n'est pas équivalente à l'une des conversions possibles detrue (la chaîne "true", la chaîne ou le nombre 1).Par contre, toutes les valeurs qui ne donnent pasfalse par conversion enboolean donnenttrue, sans exception.

Attention, les valeurs de typeobject, y compris les instances des classesString,Number etBoolean créées avec le constructeurnew sont toujours converties entrue, même lorsque leur valeur est "", 0 oufalse (la seule exception estnull qui est de typeobject et dont la conversion en booléen estfalse). Cependant la comparaison avecfalse fonctionne de la même façon qu'avec des valeurs littérales.

object

[modifier |modifier le wikicode]

Une variable de typeobject assume pleinement sa nature. Les autres types de variables, dits "scalaires", se comportent comme s'ils étaient eux-mêmes une valeur. Ainsi, lorsqu'on passe une variable scalaire à une expression, sa valeur est clonée. En revanche, passer une variable de typeobject ne fait que copier la référence, et la valeur n'est pas clonée.

L'existence de "classes" en JavaScript est discutée. Le langage ne possède pas de déclaration de classe en tant que telle. Pour cette raison, l'utilisation de ce terme sera mise entre guillemets.

Il existe trois manières de créer une variable de typeobject.

  • implicitement par l'expression littérale d'une valeur non-scalaire (valable uniquement quand une expression littérale existe pour la "classe" voulue)
  • explicitement avecnew et le constructeur (valable pour toutes les "classes" sauf les objet du DOM)
  • indirectement pour les objets du DOM (et on ne peut pas utilisernew avec eux)

L'instanciation explicite d'un objet grâce à un constructeur s'effectue avecl'opérateurnew.

t=newArray();alert(typeoft)// Affiche "object"

Les expressions littérales de chaînes, nombres et booléens créent des variables scalaires alors que le constructeur de ces types crée un objet (explicitement de typeobject et donc strictement différents d'une valeur scalaire équivalente). Mais les expressions littérales de fonctions, tableaux et expressions rationnelles créent des objets, car ce ne sont pas des types scalaires. Ces objets, instanciés sans utilisation denew, sont néanmoins strictement identiques à leur équivalent produit par l'appel d'un constructeur. Par exemple :

// valeur scalaire vs. objet"chaîne"!==newString("chaîne")2.34!==newNumber(2.34)// objet vs. objet... c'est pareil !["a","b","c"]===newArray("a","b","c")/(\w+) ?\(/i===newRegExp("(\w+) ?\(","i")

On peut créer un objet générique (qui sera simplement une instance de la "classe"Object) avec la notation littérale. Cela consiste à écrire, entre accolades, une liste de couples clé : valeur séparés par des virgules, la clé pouvant être un identifiant ou bien une chaîne, et la valeur pouvant être n'importe quelle valeur. La clé et la valeur sont séparés par deux points (':').

objetLitteral={nom:"Mac OS X",version:10.5,"nom de code":"Leopard"}

Attention, dans l'exemple ci-dessus, on ne pourra accéder à la dernière propriété ("nom de code") de l'objet qu'avec la notation tableau (avec des crochets), pas la notation objet (avec des points) car ce n'est pas un identifiant valide (il y a des espaces dedans).

Le DOM (aussi bien W3C que IE) définit certaines "classes" : HTMLElement, HTMLTextNode, HTMLDocument, CSSRuleSet, CSSRule, etc. On doit utiliser les méthodes du DOM (comme document.createElement()) pour instancier ces objets (le "DOM 0" fait exception à cette règle et à bien d'autres).

Les autres "classes" d'objets ne peuvent être créés que par un constructeur. Il y a des constructeurs natifs tels queDate, et on peut définir un constructeur soi-même. Pour plus de détails, voir le chapitre consacré aux objets.

function

[modifier |modifier le wikicode]

La différence essentielle entre une variable de type function et une variable de type object, est qu'on peut appeler une fonction. Dans les deux sens du terme :

  • une fonction peut êtrenommée, par un identifiant autre que le nom de la variable qui la référence
  • une fonction peut êtreinvoquée

Attention : ne pas confondre le type de variable ("object", "function") avec les constructeurs homonymes (Object,Function). Une variable de type "object" peut avoir n'importe quel constructeur sauf Function et bien des comportements différents, tous différents du comportement d'une fonction. Mais cette section est uniquement consacrée autype "function".

Contrairement aux autres types, le type "function" n'a pas de valeur spéciale (telle queNaN pour "number" ounull pour "object"). Il n'y a aucun moyen de convertir directement un autre type en fonction.

Une fonction est créée par l'expression littérale (exemple ci-dessous) ou bien par le constructeur Function.

functionfibonacci(n){if(isNaN(n)||n<0)returnundefinedn=Math.floor(n)varu=1,v=0while(n--)u=v+(v=u)returnv}

Cette déclaration crée une variable "fibonacci" qui référence la fonction, mais c'est aussi une opération qui retourne la référence de la fonction, que l'on peut ainsi affecter à une autre variable. Il est d'ailleurs possible de déclarer une fonction anonyme. De plus, toute nouvelle fonction reçoit automatiquement une propriétéprototype identique au prototype de la fonction Object.

L'appel se fait en ouvrant et fermant une paire de parenthèses juste après une expression dont la valeur est de type "function". Cette expression n'est pas obligatoirement le nom d'une fonction, ni même un identifiant. Cette signification des parenthèses est prioritaire sur la signification générale (forcer une expression à être évaluée avant celles qui l'entourent).

f=fibonaccideletefibonacci// efface seulement la variable, pas la fonction, qui est toujours référencée par fx=f(10);// Constitue l'appel de la fonction fibonacci, en lui passant un argumentalert(f)// affiche le code de la fonction, y compris le nom donné dans sa déclaration, "fibonacci"

Les opérateurs et méthodes qui acceptent des objets comme opérande ou argument fonctionnent pareil avec des fonctions, notamment le point pour accéder aux propriétés de la fonction.L'opérateurnew n'accepte que des fonctions comme opérande.

Par défaut, la conversion d'une fonction en chaîne retourne le code source de la fonction,préalablement reformaté par l'interpréteur JavaScript : les point-virgules, sauts de ligne et indentations seront normalisés.

Récupérée de "https://fr.wikibooks.org/w/index.php?title=Programmation_JavaScript/Variables&oldid=680801"
Catégorie :

[8]ページ先頭

©2009-2025 Movatter.jp