Nouveautés dans JavaScript 1.7

  • Raccourci de la révision : Nouveautés_dans_JavaScript_1.7
  • Titre de la révision : Nouveautés dans JavaScript 1.7
  • ID de la révision : 280879
  • Créé :
  • Créateur : Mozinet
  • Version actuelle ? Non
  • Commentaire détails

Contenu de la révision

Veuillez noter que ce document est encore en cours de rédaction. Certaines des nouvelles fonctionnalités mentionnées ne sont pas encore intégrées dans le logiciel, leur syntaxe peut donc changer.

JavaScript 1.7 est une mise à jour du langage qui introduit plusieurs nouvelles fonctionnalités, en particulier : des générateurs et des itérateurs, la définition de tableaux par compréhension, les expressions let et l'assignation déstructurante. Il reprend également toutes les fonctionnalités de JavaScript 1.6.

JavaScript 1.7 est disponible dans Firefox 2 bêta 1 et ultérieur.

Les exemples de code fournis dans cet article peuvent être essayés dans le shell JavaScript. Consultez Introduction au shell JavaScript pour apprendre comment mettre en place et utiliser le shell.

Générateurs et itérateurs

Au cours du développement de code utilisant un algorithme itératif (comme le parcours d'une liste, ou des calculs répétitifs sur le même jeu de données), on rencontre souvent des variables d'état dont les valeurs doivent être conservées tout au long du processus de calcul. Traditionnellement, on utilise une fonction de callback pour obtenir les valeurs intermédiaires d'un algorithme itératif.

Générateurs

Prenons cet algorithme itératif calculant les nombres de Fibonacci :

function do_callback(num) {
  print(num);
}

function fib() {
  var i = 0, j = 1, n = 0;
  while (n < 10) {
    do_callback(i);
    var t = i;
    i = j;
    j += t;
    n++;
  }
}

fib();

Ce code utilise une routine de callback pour réaliser des opérations à chaque étape itérative de l'algorithme. Dans ce cas, chaque nombre de Fibonacci est simplement affiché dans la console.

Les nouveaux générateurs et itérateurs fonctionnent ensemble pour fournir une meilleure manière de faire ceci. Voyons à quoi ressemble la routine des nombres de Fibonacci lorsqu'on utilise un générateur :

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i < 10; i++) {
  print(g.next());
}

La fonction contenant le mot-clé yield est un générateur. Lorsqu'on l'appelle, ses paramètres formels sont liés aux arguments effectifs, mais son corps n'est pas évalué. Au lieu de cela, un générateur-itérateur est renvoyé. Chaque appel à la méthode next() du générateur-itérateur provoque un nouveau passage au travers de l'algorithme itératif. La valeur à chaque étape est celle spécifiée par le mot-clé yield. Pensez à yield comme la version générateur-itérateur de return, indiquant la limite entre chaque itération de l'algorithme. Chaque fois que next() est appelée, le code du générateur reprend à l'instruction suivant le yield.

On cycle dans un générateur-itérateur en appelant à plusieurs reprises sa méthode next() jusqu'à ce que la condition résultante désirée soit atteinte. Dans cet exemple, on peut obtenir autant de nombres de Fibonacci que l'on veut en continuant à appeler g.next() jusqu'à ce que le nombre de résultats voulu soit atteint.

Itérateurs

Un itérateur est un objet spécial qui permet un parcours itératif de données.

Dans leur utilisation normale, les objets itérateurs sont « invisibles » ; il n'est pas nécessaire de les utiliser explicitement, mais on utilisera plutôt les instructions JavaScript for...in et for each...in pour boucler de manière naturelle sur les clés et/ou valeurs des objets.

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  print(i);
}

Si vous implémentez votre propre objet itérateur, ou avez besoin pour une autre raison de manipuler des itérateurs, vous devrez connaître la méthode next, l'exception StopIteration et la propriété __iterator__.

On peut créer un itérateur pour un objet en appelant Iterator(nomdobjet) ; l'itérateur d'un objet peut être trouvé en utilisant sa propriété __iterator__, qui par défaut implémente l'itération selon le modèle habituel for...in et for each...in. Si vous voulez fournir un itérateur personnalisé, vous devez écraser l'accesseur pour __iterator__ afin qu'il renvoie une instance de votre itérateur personnalisé. Pour obtenir un itérateur d'objet depuis un script, vous devriez utiliser Iterator(obj) plutôt qu'accéder à la propriété __iterator__ directement.

Une fois l'itérateur obtenu, il est facile de passer à l'élément suivant dans l'objet en appelant la méthode next() de l'itérateur. S'il n'y a plus de donnée à parcourir, l'exception StopIteration est déclenchée.

Voici un exemple simple de manipuation directe d'un itérateur :

var obj = {name:"Jack Bauer", username:"JackB", id:12345, agency:"CTU", region:"Los Angeles"};

var it = Iterator(obj);

try {
  while (true) {
    print(it.next());
  }
} catch (err if err == StopIteration) {
  print("End of record.\n");
} catch (err) {
  print("Unknown error: " + err.description + "\n");
}

Le résultat affiché par ce programme ressemble à ceci :

name,Jack Bauer
username,JackB
id,12345
agency,CTU
region,Los Angeles
End of record.

Il est possible, optionnellement, de spécifier un second paramètre à la création de l'itérateur, qui est une valeur booléenne indiquant si seules les clés doivent être renvoyées à chaque fois que la méthode next() est appelée. Si on change var it = Iterator(obj); en var it = Iterator(obj, true); dans l'exemple ci-dessus, on obtient le résultat suivant :

name
username
id
agency
region
End of record.

Dans les deux cas, l'ordre réel dans lequel les données sont renvoyées peut varier selon l'implémentation. Aucun ordre n'est garanti dans les données.

Les itérateurs sont une manière pratique de parcourir les données dans des objets, même les objets qui peuvent contenir des données dont vous ne connaissez pas l'existence. C'est particulièrement utile dans le cas où des données non attendues par votre application doivent toutefois être préservées.

Définition de tableaux par compréhension

Les tableaux définis par compréhension sont une utilisation des générateurs fournissant une manière pratique et puissante d'initialiser des tableaux. Par exemple :

function range(begin, end) {
  for (let i = begin; i < end; ++i) {
    yield i;
  }
}

range() est un générateur renvoyant toutes les valeurs entre <tt>begin</tt> et <tt>end</tt>. Une fois cete fonction définie, on peut l'utiliser comme ceci :

var ten_squares = [i * i for (i in range(0, 10))];

Un nouveau tableau ten_squares est préinitialisé pour contenir les carrés des valeurs dans l'intervalle 0..9.

On peut préciser n'importe quelle condition à l'initialisation du tableau. Si vous voulez initialiser un tableau pour contenir les nombres pairs entre 0 et 20, vous pouvez utiliser ce code :

var evens = [i for (i in range(0, 21)) if (i % 2 == 0)];

Avant JavaScript 1.7, il aurait été nécessaire d'écrire quelque chose de semblable à ceci :

var evens = [];
for (var i=0; i <= 20; i++) {
  if (i % 2 == 0)
    evens.push(i);
}

La notation par compréhension est non seulement plus compacte, mais elle est également plus facile à lire une fois familiarisé avec le concept.

Règles de portée

Les définitions de tableaux par compréhension ont un bloc implicite autour d'elles, contenant tout ce qui se trouve entre les crochets droits, ainsi que des déclarations let implicites.

Plus de détails sont nécessaires.

Portée des variables avec let

L'instruction let

L'instruction let fournit une portée locale pour les variables, constantes et fonctions, et est prévue pour être utilisée à la place de var. Elle fonctionne en liant un ensemble de variables à un seul bloc de code. La valeur de terminaison de l'instruction let est celle du bloc.

Par exemple :

var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  print(x+y);
}

print(x+y);

L'affichage produit par ce programme sera :

27
5

Les règles pour le bloc de code sont les mêmes que pour n'importe quel autre bloc de code en JavaScript. Il peut avoir ses propres variables locales établies à l'aide de l'instruction var. Comme d'habitude, vous ne pouvez pas déclarer de fonctions au sein d'un bloc.

Note : Les parenthèses suivant let sont ici obligatoires. Leur absence résulterait en une erreur de syntaxe.
Règles de portée

La portée des variables définies à l'aide de let est le bloc let lui-même, ainsi que tout bloc interne contenu à l'intérieur de celui-ci, à moins que ces blocs définissent des variables ayant les mêmes noms.

Expressions avec let

On peut utiliser let pour définir des variables dont la portée se limitent à une seule expression :

var x = 5;
var y = 0;
print( let(x = x + 10, y = 12) x+y );
print(x+y);

L'affichage produit est :

27
5

Dans ce cas, la liaison entre les valeurs de x et y, et les expressions x+10 et 12 a une portée limitée uniquement à l'expression x+y.

Règles de portée

Avec une expression let donnée :

let (decls) expr

Un bloc implicite est créé autour de expr.

Définitions avec let

Le mot-clé let peut également être utilisé pour définir des variables, constantes et fonctions au sein d'un bloc.

if (x > y)
{
   let const k = 37;
   let gamma : int = 12.7 + k;
   let i = 10;
   let function f(n) { return (n/3)+k; }
   return f(gamma) + f(i);
}
Règles de portée

Les variables, fonctions et constantes déclarées avec let, let function et let const ont leur portée limitée au bloc dans lequel elles sont définies, ainsi que dans tout sous-bloc dans lequel elles ne sont pas redéfinies. Dans ce sens, let fonctionne tout à fait comme var.

Dans les programmes et classes, let ne crée pas de propriétés sur les objets global et de classe comme le ferait var ; au lieu de cela, des propriétés sont créées dans un bloc implicite créé pour l'évaluation des instructions dans ces contextes. Essentiellement, cela signifie que let n'écrasera pas de variables définies précédemment avec var. Par exemple :

var x = 'global';
let x = 42;
alert(this.x);

L'alerte déclenchée par ce code affichera « global », et non « 42 ».

Un bloc implicite est un bloc non entouré de crochets ; il est créé implicitement par le moteur JavaScript.

Dans les fonctions, let lorsqu'il est exécuté par eval() ne crée pas de propriétés sur l'objet de la variable (objet d'activation ou de liaison interne) comme var le ferait ; au lieu de cela, des propriétés sont créées dans un bloc implicite créé pour l'évaluation d'instuctions dans le programme. Il s'agit d'une conséquence du comportement d'eval() sur des programmes combiné avec la règle qui précède.

Autrement dit, lorsqu'eval() est utilisé pour exécuter du code, ce code est traité comme un programme indépendant, qui a son propre bloc implicite autour de son code.

Variables déclarées avec let dans des boucles for loops

Le mot-clé let peut être utilisé pour lier des variables localement dans la portée de boucles for, exactement comme avec var.

   var i=0;
   for ( let i=i ; i < 10 ; i++ )
     print(i);

   for ( let &[name,value] in obj )
     print("Name: " + name + ", Value: " + value);
Règles de portée
for (let expr1; expr2; expr3) statement

Dans cet exemple, expr2, expr3 et statement font partie d'un bloc implicite contenant les variables de bloc déclarées avec let expr1. C'est ce qui est montré dans la première boucle ci-dessus.

for (expr1 in expr2) statement

Dans ce cas, un bloc implicite contient statement. C'est ce qui est montré dans la seconde boucle ci-dessus.

Assignation déstructurante

L'assignation déstructurente rend possible l'extraction de données depuis des tableaux ou des objets en utilisant une syntaxe semblable aux déclarations littérales de tableaux et d'objets.

Un avantage clé de l'assignation déstructurante est la possiblité pour des fonctions de renvoyer plusieurs valeurs.

Cette section sera améliorée lorsque l'auteur aura eu l'occasion d'expérimenter la fonctionnalité.

Cette possibilité est similaire à celles qui sont présentes dans des langages comme Perl et Python.

Renvoi de valeurs multiples

Grâce à l'assignation déstructurante, les fonctions peuvent renvoyer plusieurs valeurs :

function f() {
  return [1, 2];
}

var a, b;
[a, b] = f();

Après exécution de ce code, a vaut 1 et b vaut 2.

Il est également possible d'ignorer les valeurs de retour qui ne vous intéressent pas :

function f() {
  return [1, 2, 3];
}

var [a, , b] = f();

Après exécution de ce code, a vaut 1 et b vaut 3. La valeur 2 est ignorée. Il est possible d'ignorer toute (ou toutes les) valeur(s) renvoyée(s) de cette manière. Par exemple :

[,,,] = f();

Parcours d'objets

L'assignation déstructurante peut également être utilisée pour extraire des données d'un objet :

for (let[name, value] in obj) {
  print("Name: " + name + ", Value: " + value);
}

Ceci récupère les champs name et value d'un objet obj et les affiche.

Parcours des valeurs d'un objet

Il est possible de parcourir les valeur d'un objet de la même manière :

for each (let {name: n, family: { father: f } } in obj) {
  print("Name: " + n + ", Father: " + f);
}

Manque une explication sur ce que cela fait

Capture de lignes et mise à jour d'enregistrements

Liée à l'assignation déstructurante, la capture de lignes permet de récupérer des champs individuels d'une structure, ainsi qu'une nouvelle structure contenant les champs que vous n'avez pas explicitement extraits.

Par exemple :

var personRecord = { name: "Bob", city: "Foohaven", job: "Programmer", employer: "Barco Inc." };

{ name: x, city: y, ...: z } = personRecord;

Ce code extrait les champs name et city dans les variables x et y, respectivement, et crée également une nouvelle structure, z, qui contient { job: "Programmer", employer: "Barco Inc." }.

Une utilisation pratique de cette possibilité est la préservation de données. Si votre code doit être capable de travailler sur des données pouvant contenir des champs dont vous n'avez pas connaissance, vous pouvez extraire les champs inconnus dans une structure pour les préserver même si vous ne connaissez pas leurs noms.

Les valeurs et structures peuvent également être combinées ensemble à l'aide de cette syntaxe. Par exemple, si Bob déménage, il faut changer le champ city dans l'enregistrement ci-dessus. Après cela, l'enregistrement complet peut être reconstruit avec les nouvelles données.

Cela peut se faire très facilement, comme ceci :

var newPersonRecord = { ... = z, city = "New Foohaven" };

Après cela, newPersonRecord contient { name: "Bob", city: "New Foohaven", job: "Programmer", employer: "Barco Inc." }.

En termes simples, « ... » est un raccourci pour « tout champ que je n'ai pas explicitement mentionné. »

{{ wiki.languages( { "en": "en/New_in_JavaScript_1.7", "pl": "pl/Nowo\u015bci_w_JavaScript_1.7" } ) }}

Source de la révision

<div class="note">
<p><i>Veuillez noter que ce document est encore en cours de rédaction. Certaines des nouvelles fonctionnalités mentionnées ne sont pas encore intégrées dans le logiciel, leur syntaxe peut donc changer.</i>
</p>
</div>
<p>JavaScript 1.7 est une mise à jour du langage qui introduit plusieurs nouvelles fonctionnalités, en particulier : des générateurs et des itérateurs, la définition de tableaux par compréhension, les expressions <code>let</code> et l'assignation déstructurante. Il reprend également toutes les fonctionnalités de <a href="fr/Nouveaut%c3%a9s_dans_JavaScript_1.6">JavaScript 1.6</a>.
</p><p>JavaScript 1.7 est disponible dans <a href="fr/Firefox_2">Firefox 2</a> bêta 1 et ultérieur.
</p><p>Les exemples de code fournis dans cet article peuvent être essayés dans le shell JavaScript. Consultez <a href="fr/Introduction_au_shell_JavaScript">Introduction au shell JavaScript</a> pour apprendre comment mettre en place et utiliser le shell.
</p>
<h3 name="G.C3.A9n.C3.A9rateurs_et_it.C3.A9rateurs"> Générateurs et itérateurs </h3>
<p>Au cours du développement de code utilisant un algorithme itératif (comme le parcours d'une liste, ou des calculs répétitifs sur le même jeu de données), on rencontre souvent des variables d'état dont les valeurs doivent être conservées tout au long du processus de calcul. Traditionnellement, on utilise une fonction de callback pour obtenir les valeurs intermédiaires d'un algorithme itératif.
</p>
<h4 name="G.C3.A9n.C3.A9rateurs"> Générateurs </h4>
<p>Prenons cet algorithme itératif calculant les nombres de Fibonacci :
</p>
<pre>function do_callback(num) {
  print(num);
}

function fib() {
  var i = 0, j = 1, n = 0;
  while (n &lt; 10) {
    do_callback(i);
    var t = i;
    i = j;
    j += t;
    n++;
  }
}

fib();
</pre>
<p>Ce code utilise une routine de callback pour réaliser des opérations à chaque étape itérative de l'algorithme. Dans ce cas, chaque nombre de Fibonacci est simplement affiché dans la console.
</p><p>Les nouveaux générateurs et itérateurs fonctionnent ensemble pour fournir une meilleure manière de faire ceci. Voyons à quoi ressemble la routine des nombres de Fibonacci lorsqu'on utilise un générateur :
</p>
<pre>function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i &lt; 10; i++) {
  print(g.next());
}
</pre>
<p>La fonction contenant le mot-clé <code>yield</code> est un générateur. Lorsqu'on l'appelle, ses paramètres formels sont liés aux arguments effectifs, mais son corps n'est pas évalué. Au lieu de cela, un générateur-itérateur est renvoyé. Chaque appel à la méthode <code>next()</code> du générateur-itérateur provoque un nouveau passage au travers de l'algorithme itératif. La valeur à chaque étape est celle spécifiée par le mot-clé <code>yield</code>. Pensez à <code>yield</code> comme la version générateur-itérateur de <code>return</code>, indiquant la limite entre chaque itération de l'algorithme. Chaque fois que <code>next()</code> est appelée, le code du générateur reprend à l'instruction suivant le <code>yield</code>.
</p><p>On cycle dans un générateur-itérateur en appelant à plusieurs reprises sa méthode <code>next()</code> jusqu'à ce que la condition résultante désirée soit atteinte. Dans cet exemple, on peut obtenir autant de nombres de Fibonacci que l'on veut en continuant à appeler <code>g.next()</code> jusqu'à ce que le nombre de résultats voulu soit atteint.
</p>
<h4 name="It.C3.A9rateurs"> Itérateurs </h4>
<p>Un <i>itérateur</i> est un objet spécial qui permet un parcours itératif de données.
</p><p>Dans leur utilisation normale, les objets itérateurs sont « invisibles » ; il n'est pas nécessaire de les utiliser explicitement, mais on utilisera plutôt les instructions JavaScript <a href="fr/Guide_JavaScript_1.5/Instructions_de_manipulation_d'objets"><code>for...in</code> et <code>for each...in</code></a> pour boucler de manière naturelle sur les clés et/ou valeurs des objets.
</p>
<pre>var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  print(i);
}
</pre>
<p>Si vous implémentez votre propre objet itérateur, ou avez besoin pour une autre raison de manipuler des itérateurs, vous devrez connaître la méthode <code>next</code>, l'exception <code>StopIteration</code> et la propriété <code>__iterator__</code>.
</p><p>On peut créer un itérateur pour un objet en appelant <code>Iterator(<i>nomdobjet</i>)</code> ; l'itérateur d'un objet peut être trouvé en utilisant sa propriété <code>__iterator__</code>, qui par défaut implémente l'itération selon le modèle habituel <code>for...in</code> et <code>for each...in</code>. Si vous voulez fournir un itérateur personnalisé, vous devez écraser <a href="fr/Guide_JavaScript_1.5/Cr%c3%a9ation_d'objets/D%c3%a9finition_d'accesseurs_et_de_mutateurs">l'accesseur</a> pour <code>__iterator__</code> afin qu'il renvoie une instance de votre itérateur personnalisé. Pour obtenir un itérateur d'objet depuis un script, vous devriez utiliser  <code>Iterator(<i>obj</i>)</code> plutôt qu'accéder à la propriété <code>__iterator__</code> directement.
</p><p>Une fois l'itérateur obtenu, il est facile de passer à l'élément suivant dans l'objet en appelant la méthode <code>next()</code> de l'itérateur. S'il n'y a plus de donnée à parcourir, l'exception <code>StopIteration</code> est déclenchée.
</p><p>Voici un exemple simple de manipuation directe d'un itérateur :
</p>
<pre>var obj = {name:"Jack Bauer", username:"JackB", id:12345, agency:"CTU", region:"Los Angeles"};

var it = Iterator(obj);

try {
  while (true) {
    print(it.next());
  }
} catch (err if err == StopIteration) {
  print("End of record.\n");
} catch (err) {
  print("Unknown error: " + err.description + "\n");
}
</pre>
<p>Le résultat affiché par ce programme ressemble à ceci :
</p>
<pre>name,Jack Bauer
username,JackB
id,12345
agency,CTU
region,Los Angeles
End of record.
</pre>
<p>Il est possible, optionnellement, de spécifier un second paramètre à la création de l'itérateur, qui est une valeur booléenne indiquant si seules les clés doivent être renvoyées à chaque fois que la méthode <code>next()</code> est appelée. Si on change <code>var it = Iterator(obj);</code> en <code>var it = Iterator(obj, true);</code> dans l'exemple ci-dessus, on obtient le résultat suivant :
</p>
<pre>name
username
id
agency
region
End of record.
</pre>
<p>Dans les deux cas, l'ordre réel dans lequel les données sont renvoyées peut varier selon l'implémentation. Aucun ordre n'est garanti dans les données.
</p><p>Les itérateurs sont une manière pratique de parcourir les données dans des objets, même les objets qui peuvent contenir des données dont vous ne connaissez pas l'existence. C'est particulièrement utile dans le cas où des données non attendues par votre application doivent toutefois être préservées.
</p>
<h3 name="D.C3.A9finition_de_tableaux_par_compr.C3.A9hension"> Définition de tableaux par compréhension </h3>
<p>Les tableaux définis par compréhension sont une utilisation des générateurs fournissant une manière pratique et puissante d'initialiser des tableaux. Par exemple :
</p>
<pre class="eval">function range(begin, end) {
  for (let i = begin; i &lt; end; ++i) {
    yield i;
  }
}
</pre>
<p><code>range()</code> est un générateur renvoyant toutes les valeurs entre <tt>begin</tt> et <tt>end</tt>. Une fois cete fonction définie, on peut l'utiliser comme ceci :
</p>
<pre class="eval">var ten_squares = [i * i for (i in range(0, 10))];
</pre>
<p>Un nouveau tableau <var>ten_squares</var> est préinitialisé pour contenir les carrés des valeurs dans l'intervalle <code>0..9</code>.
</p><p>On peut préciser n'importe quelle condition à l'initialisation du tableau. Si vous voulez initialiser un tableau pour contenir les nombres pairs entre 0 et 20, vous pouvez utiliser ce code :
</p>
<pre class="eval">var evens = [i for (i in range(0, 21)) if (i % 2 == 0)];
</pre>
<p>Avant JavaScript 1.7, il aurait été nécessaire d'écrire quelque chose de semblable à ceci :
</p>
<pre>var evens = [];
for (var i=0; i &lt;= 20; i++) {
  if (i % 2 == 0)
    evens.push(i);
}
</pre>
<p>La notation par compréhension est non seulement plus compacte, mais elle est également plus facile à lire une fois familiarisé avec le concept.
</p>
<h4 name="R.C3.A8gles_de_port.C3.A9e"> Règles de portée </h4>
<p>Les définitions de tableaux par compréhension ont un bloc implicite autour d'elles, contenant tout ce qui se trouve entre les crochets droits, ainsi que des déclarations <code>let</code> implicites.
</p><p><i>Plus de détails sont nécessaires.</i>
</p>
<h3 name="Port.C3.A9e_des_variables_avec_let"> Portée des variables avec <code>let</code> </h3>
<h4 name="L.27instruction_let"> L'instruction <code>let</code> </h4>
<p>L'instruction <code>let</code> fournit une portée locale pour les variables, constantes et fonctions, et est prévue pour être utilisée à la place de <code>var</code>. Elle fonctionne en liant un ensemble de variables à un seul bloc de code. La valeur de terminaison de l'instruction <code>let</code> est celle du bloc.
</p><p>Par exemple :
</p>
<pre>var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  print(x+y);
}

print(x+y);
</pre>
<p>L'affichage produit par ce programme sera :
</p>
<pre>27
5
</pre>
<p>Les règles pour le bloc de code sont les mêmes que pour n'importe quel autre bloc de code en JavaScript. Il peut avoir ses propres variables locales établies à l'aide de l'instruction <code>var</code>. Comme d'habitude, vous ne pouvez pas déclarer de fonctions au sein d'un bloc.
</p>
<div class="note"><b>Note :</b> Les parenthèses suivant <code>let</code> sont ici obligatoires. Leur absence résulterait en une erreur de syntaxe.</div>
<h5 name="R.C3.A8gles_de_port.C3.A9e_2"> Règles de portée </h5>
<p>La portée des variables définies à l'aide de <code>let</code> est le bloc <code>let</code> lui-même, ainsi que tout bloc interne contenu à l'intérieur de celui-ci, à moins que ces blocs définissent des variables ayant les mêmes noms.
</p>
<h4 name="Expressions_avec_let"> Expressions avec <code>let</code> </h4>
<p>On peut utiliser <code>let</code> pour définir des variables dont la portée se limitent à une seule expression :
</p>
<pre class="eval">var x = 5;
var y = 0;
print( let(x = x + 10, y = 12) x+y );
print(x+y);
</pre>
<p>L'affichage produit est :
</p>
<pre class="eval">27
5
</pre>
<p>Dans ce cas, la liaison entre les valeurs de <var>x</var> et <var>y</var>, et les expressions <code>x+10</code> et <code>12</code> a une portée limitée uniquement à l'expression <code>x+y</code>.
</p>
<h5 name="R.C3.A8gles_de_port.C3.A9e_3"> Règles de portée </h5>
<p>Avec une expression <code>let</code> donnée :
</p>
<pre class="eval">let (<var>decls</var>) <var style="color: blue">expr</var>
</pre>
<p>Un bloc implicite est créé autour de <var style="color: blue">expr</var>.
</p>
<h4 name="D.C3.A9finitions_avec_let"> Définitions avec <code>let</code> </h4>
<p>Le mot-clé <code>let</code> peut également être utilisé pour définir des variables, constantes et fonctions au sein d'un bloc.
</p>
<pre>if (x &gt; y)
{
   let const k = 37;
   let gamma : int = 12.7 + k;
   let i = 10;
   let function f(n) { return (n/3)+k; }
   return f(gamma) + f(i);
}
</pre>
<h5 name="R.C3.A8gles_de_port.C3.A9e_4"> Règles de portée </h5>
<p>Les variables, fonctions et constantes déclarées avec <code>let</code>, <code>let function</code> et <code>let const</code> ont leur portée limitée au bloc dans lequel elles sont définies, ainsi que dans tout sous-bloc dans lequel elles ne sont pas redéfinies. Dans ce sens, <code>let</code> fonctionne tout à fait comme <code>var</code>.
</p><p>Dans les programmes et classes, <code>let</code> ne crée pas de propriétés sur les objets global et de classe comme le ferait <code>var</code> ; au lieu de cela, des propriétés sont créées dans un bloc implicite créé pour l'évaluation des instructions dans ces contextes. Essentiellement, cela signifie que <code>let</code> n'écrasera pas de variables définies précédemment avec <code>var</code>. Par exemple :
</p>
<pre class="eval">var x = 'global';
let x = 42;
alert(this.x);
</pre>
<p>L'alerte déclenchée par ce code affichera « global », et non « 42 ».
</p><p>Un <i>bloc implicite</i> est un bloc non entouré de crochets ; il est créé implicitement par le moteur JavaScript.
</p><p>Dans les fonctions, <code>let</code> lorsqu'il est exécuté par <code>eval()</code> ne crée pas de propriétés sur l'objet de la variable (objet d'activation ou de liaison interne) comme <code>var</code> le ferait ; au lieu de cela, des propriétés sont créées dans un bloc implicite créé pour l'évaluation d'instuctions dans le programme. Il s'agit d'une conséquence du comportement d'<code>eval()</code> sur des programmes combiné avec la règle qui précède.
</p><p>Autrement dit, lorsqu'<code>eval()</code> est utilisé pour exécuter du code, ce code est traité comme un programme indépendant, qui a son propre bloc implicite autour de son code.
</p>
<h4 name="Variables_d.C3.A9clar.C3.A9es_avec_let_dans_des_boucles_for_loops"> Variables déclarées avec <code>let</code> dans des boucles <code>for</code> loops </h4>
<p>Le mot-clé <code>let</code> peut être utilisé pour lier des variables localement dans la portée de boucles <code>for</code>, exactement comme avec <code>var</code>.
</p>
<pre>   var i=0;
   for ( let i=i ; i &lt; 10 ; i++ )
     print(i);

   for ( let &amp;[name,value] in obj )
     print("Name: " + name + ", Value: " + value);
</pre>
<h5 name="R.C3.A8gles_de_port.C3.A9e_5"> Règles de portée </h5>
<pre class="eval">for (let <var>expr1</var>; <var style="color: blue">expr2</var>; <var style="color: blue">expr3</var>) <var style="color: blue">statement</var>
</pre>
<p>Dans cet exemple, <var style="color: blue">expr2</var>, <var style="color: blue">expr3</var> et <var style="color: blue">statement</var> font partie d'un bloc implicite contenant les variables de bloc déclarées avec <code>let <var>expr1</var></code>. C'est ce qui est montré dans la première boucle ci-dessus.
</p>
<pre class="eval">for (<var>expr1</var> in <var>expr2</var>) <var style="color: blue">statement</var>
</pre>
<p>Dans ce cas, un bloc implicite contient <var style="color: blue">statement</var>. C'est ce qui est montré dans la seconde boucle ci-dessus.
</p>
<h3 name="Assignation_d.C3.A9structurante"> Assignation déstructurante </h3>
<p>L'assignation déstructurente rend possible l'extraction de données depuis des tableaux ou des objets en utilisant une syntaxe semblable aux déclarations littérales de tableaux et d'objets.
</p><p>Un avantage clé de l'assignation déstructurante est la possiblité pour des fonctions de renvoyer plusieurs valeurs.
</p><p><i>Cette section sera améliorée lorsque l'auteur aura eu l'occasion d'expérimenter la fonctionnalité.</i>
</p><p>Cette possibilité est similaire à celles qui sont présentes dans des langages comme Perl et Python.
</p>
<h4 name="Renvoi_de_valeurs_multiples"> Renvoi de valeurs multiples </h4>
<p>Grâce à l'assignation déstructurante, les fonctions peuvent renvoyer plusieurs valeurs :
</p>
<pre>function f() {
  return [1, 2];
}

var a, b;
[a, b] = f();
</pre>
<p>Après exécution de ce code, <var>a</var> vaut 1 et <var>b</var> vaut 2.
</p><p>Il est également possible d'ignorer les valeurs de retour qui ne vous intéressent pas :
</p>
<pre>function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
</pre>
<p>Après exécution de ce code, <var>a</var> vaut 1 et <var>b</var> vaut 3. La valeur 2 est ignorée. Il est possible d'ignorer toute (ou toutes les) valeur(s) renvoyée(s) de cette manière. Par exemple :
</p>
<pre class="eval">[,,,] = f();
</pre>
<h4 name="Parcours_d.27objets"> Parcours d'objets </h4>
<p>L'assignation déstructurante peut également être utilisée pour extraire des données d'un objet :
</p>
<pre>for (let[name, value] in obj) {
  print("Name: " + name + ", Value: " + value);
}
</pre>
<p>Ceci récupère les champs <var>name</var> et <var>value</var> d'un objet <var>obj</var> et les affiche.
</p>
<h4 name="Parcours_des_valeurs_d.27un_objet"> Parcours des valeurs d'un objet </h4>
<p>Il est possible de parcourir les valeur d'un objet de la même manière :
</p>
<pre>for each (let {name: n, family: { father: f } } in obj) {
  print("Name: " + n + ", Father: " + f);
}
</pre>
<p><i>Manque une explication sur ce que cela fait</i>
</p>
<h3 name="Capture_de_lignes_et_mise_.C3.A0_jour_d.27enregistrements"> Capture de lignes et mise à jour d'enregistrements </h3>
<p>Liée à l'assignation déstructurante, la capture de lignes permet de récupérer des champs individuels d'une structure, ainsi qu'une nouvelle structure contenant les champs que vous n'avez pas explicitement extraits.
</p><p>Par exemple :
</p>
<pre>var personRecord = { name: "Bob", city: "Foohaven", job: "Programmer", employer: "Barco Inc." };

{ name: x, city: y, ...: z } = personRecord;
</pre>
<p>Ce code extrait les champs <var>name</var> et <var>city</var> dans les variables <var>x</var> et <var>y</var>, respectivement, et crée également une nouvelle structure, <var>z</var>, qui contient <code>{ job: "Programmer", employer: "Barco Inc." }</code>.
</p><p>Une utilisation pratique de cette possibilité est la préservation de données. Si votre code doit être capable de travailler sur des données pouvant contenir des champs dont vous n'avez pas connaissance, vous pouvez extraire les champs inconnus dans une structure pour les préserver même si vous ne connaissez pas leurs noms.
</p><p>Les valeurs et structures peuvent également être combinées ensemble à l'aide de cette syntaxe. Par exemple, si Bob déménage, il faut changer le champ <var>city</var> dans l'enregistrement ci-dessus. Après cela, l'enregistrement complet peut être reconstruit avec les nouvelles données.
</p><p>Cela peut se faire très facilement, comme ceci :
</p>
<pre class="eval">var newPersonRecord = { ... = z, city = "New Foohaven" };
</pre>
<p>Après cela, <var>newPersonRecord</var> contient <code>{ name: "Bob", city: "New Foohaven", job: "Programmer", employer: "Barco Inc." }</code>.
</p><p>En termes simples, « <code>...</code> » est un raccourci pour « tout champ que je n'ai pas explicitement mentionné. »
</p>{{ wiki.languages( { "en": "en/New_in_JavaScript_1.7", "pl": "pl/Nowo\u015bci_w_JavaScript_1.7" } ) }}
Revenir à cette révision