Introduction à ECMAScript 6 (ES-2015)

Introduction à ES6



Table des matières
1. Modèles de littéraux
2. let et const
3. Expressions des fonctions fléchées
4. Pour ... de
5. Noms de propriété calculés
6. Object.assign ()
7. Paramètres de repos
8. Paramètres par défaut
9. Mission de restructuration
10. Carte
11. Set
12. Classes
13. Promesse
14. Itérateurs
15. Générateurs
16. Sumbol

Littéraux de modèle (chaînes de modèle)


Les littéraux de modèle sont des littéraux de chaîne qui permettent l'utilisation d'expressions à l'intérieur. Avec eux, vous pouvez utiliser des littéraux multilignes et une interpolation de chaînes.

Les littéraux de modèle sont entourés de guillemets (``) au lieu de doubles ou simples. Ils peuvent contenir des caractères génériques indiqués par un signe dollar et des accolades ($ {expression}). Les expressions de substitution et le texte entre elles sont passés à la fonction. Par défaut, la fonction concatène simplement toutes les parties dans une chaîne. S'il y a une expression avant la ligne (ici c'est tag), alors la ligne de modèle est appelée "modèle de balise". Dans ce cas, l'expression de balise (généralement une fonction) est appelée avec le littéral de modèle traité, que vous pouvez modifier avant la sortie. Pour échapper à la citation inverse dans les littéraux de modèle, spécifiez la barre oblique inverse \.

Littéraux multilignes
Les caractères de nouvelle ligne font partie des littéraux génériques. En utilisant des chaînes régulières, l'encapsulage nécessiterait la syntaxe suivante:
console.log('string text line 1\n' + 'string text line 2'); // "string text line 1 // string text line 2" 

Même chose avec l'utilisation des littéraux de modèle:
 console.log(`string text line 1 string text line 2`); // "string text line 1 // string text line 2" 


Interpolation d'expression
Pour insérer des expressions dans des chaînes régulières, vous devez utiliser la syntaxe suivante:
 var a = 5; var b = 10; console.log('Fifteen is ' + (a + b) + ' and not ' + (2 * a + b) + '.'); // "Fifteen is 15 and not 20." 


Maintenant, avec l'aide des modèles de littéraux, vous pouvez utiliser le «sucre syntaxique», ce qui rend les substitutions comme celle-ci plus lisibles:
 var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); // "Fifteen is 15 and not 20." 


Modèles imbriqués
Parfois, l'imbrication d'un motif est le moyen le plus court et peut-être le plus lisible de créer une chaîne. Mettez simplement un autre dans le modèle backquoted, en les enveloppant dans la substitution $ {}. Par exemple, si l'expression est vraie, vous pouvez renvoyer un littéral de modèle.
Dans ES5:
 var classes = 'header' classes += (isLargeScreen() ? '' : item.isCollapsed ? ' icon-expander' : ' icon-collapser'); 

Dans ES2015 avec des modèles de littéraux sans imbrication:
 const classes = `header ${ isLargeScreen() ? '' : (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`; 

Dans ES2015 avec des littéraux de modèle imbriqués:
 const classes = `header ${ isLargeScreen() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`; 


Modèles de balises
Une forme étendue de littéraux de modèle est les modèles balisés. Ils vous permettent d'analyser les littéraux de modèle à l'aide d'une fonction. Le premier argument d'une telle fonction contient un tableau de valeurs de chaîne et le reste contient des expressions de substitutions. Par conséquent, la fonction doit renvoyer la chaîne assemblée (ou quelque chose de complètement différent, comme cela sera montré plus loin). Le nom de la fonction peut être n'importe quoi.
 var person = 'Mike'; var age = 28; function myTag(strings, personExp, ageExp) { var str0 = strings[0]; // "That " var str1 = strings[1]; // " is a " // ,     // (  )    , //    (""),    . // var str2 = strings[2]; var ageStr; if (ageExp > 99){ ageStr = 'centenarian'; } else { ageStr = 'youngster'; } //     ,     return `${str0}${personExp}${str1}${ageStr}`; } var output = myTag`That ${ person } is a ${ age }`; console.log(output);// That Mike is a youngster 

La fonction de balise n'est pas requise pour renvoyer une chaîne.

Lignes brutes
La propriété brute spéciale, disponible pour le premier argument du modèle de balise, vous permet d'obtenir la chaîne sous la forme dans laquelle elle a été entrée, sans interprétation.
 function tag(strings) { return strings.raw[0]; } tag`string text line 1 \\n string text line 2`; //  "string text line 1 \\n string text line 2", //  'n'    '\' 

En outre, il existe une méthode String.raw () qui retourne exactement la même chaîne source que la fonction de modèle par défaut et la concaténation de chaîne retournerait ensemble.

Dans ECMAScript 2016, les modèles balisés suivent les règles pour échapper les caractères suivants:
  • Caractères Unicode commençant par "\ u", par exemple, \ u00A9
  • Points de code Unicode commençant par "\ u {}", par exemple, \ u {2F804}
  • représentations de caractères hexadécimaux commençant par "\ x", par exemple, \ xA9
  • représentations octales de caractères commençant par "\", par exemple, \ 251


let et const


La portée des variables déclarées par les mots clés let et const est le bloc dans lequel elles sont déclarées, et tout cela sous les blocs. En cela, le fonctionnement de la directive let est similaire à celui de la directive var. La principale différence est que la portée de la variable déclarée par la directive var est la fonction entière dans laquelle elle est déclarée. En plus des variables, la valeur des constantes ne peut pas être modifiée par une nouvelle affectation, ni redéfinie. Lors de la déclaration d'une variable avec le mot clé const, vous devez utiliser l'opérateur d'affectation pour définir la valeur de la constante.

Les constantes globales ne deviennent pas des propriétés de l'objet window, contrairement aux variables var.
L'initialisation d'une constante est requise.
Vous devez spécifier une valeur en même temps que la déclaration (le fait est qu'alors cette valeur ne peut plus être modifiée).
La déclaration de variables avec le mot clé const crée une constante (une nouvelle référence nommée à une région de mémoire) qui est en lecture seule.
Cela ne signifie pas que la valeur indiquée est inchangée, mais cela signifie que l'identifiant ne peut pas être réaffecté. Par exemple, si une constante pointe vers un objet, l'objet lui-même peut être modifié.
Les noms de constantes ne peuvent pas coïncider avec des noms de fonctions ou de variables de même étendue.

Un exemple de la différence entre la portée globale et la portée de bloc:
 function myFunction() { if (true) let a = 5; console.log(a); //SyntaxError   a     if if (true) var b = 5; console.log(b); //5   b     } 


Expressions de la fonction flèche


Les expressions de fonction de flèche ont une syntaxe plus courte que les expressions fonctionnelles et sont lexicalement liées à la valeur de this (mais pas liées à leur propre this, arguments, super ou new.target). L'expression des fonctions fléchées ne vous permet pas de spécifier un nom, par conséquent les fonctions fléchées sont anonymes sauf si elles sont affectées à quoi que ce soit.

Syntaxe de base
 (param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression // : (param1, param2, …, paramN) => { return expression; } //       : (singleParam) => { statements } singleParam => { statements } //       : () => { statements } () => expression // : () => { return expression; } 


Syntaxe étendue
 //     ,     params => ({foo: bar}) // Rest       (param1, param2, ...rest) => { statements } (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } //    var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6 

Vous trouverez plus d'informations sur les fonctions fléchées ici .

Pour ... de


L'instruction for ... of exécute une boucle à travers des objets itérables (y compris Array, Map, Set, un objet d'arguments et similaires), invoquant à chaque étape d'itération les opérateurs pour chaque valeur à partir de diverses propriétés de l'objet.

Pourquoi NE DEVRAIT PAS utiliser une boucle for ... in pour itérer? Parce que selon le moteur, JavaScript peut itérer dans un ordre aléatoire, ce qui peut conduire à des résultats imprévisibles. Si une propriété change dans une itération, puis change à nouveau, sa valeur dans la boucle est sa dernière valeur. Une propriété supprimée avant que le cycle ne l'atteigne n'y participera pas. Les propriétés ajoutées aux objets de la boucle peuvent être ignorées. En général, il est préférable de ne pas ajouter, modifier ou supprimer une propriété de l'objet pendant l'itération si vous ne l'avez pas déjà transmise. Il n'y a aucune garantie que la propriété ajoutée sera visitée par le cycle, modifiée après les modifications et supprimée après la suppression. De plus, la variable itérative est une chaîne et non un nombre, ce qui signifie que si vous souhaitez effectuer des calculs avec la variable, vous devrez concaténer les chaînes au lieu de les ajouter. Donc, pour éviter les erreurs logiques, vous ne devez pas l'utiliser!

Contrairement à la boucle for ... of, la boucle for ... in renvoie toutes les propriétés énumérées, y compris celles avec des noms non entiers et héritées.

Pour ... de la syntaxe de boucle
 for (var i of arr) //for ( of ) arr[i] = "something value" 

Exemples:
 Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; iterable.foo = 'hello'; for (let i in iterable) console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom" for (let i in iterable) { if (iterable.hasOwnProperty(i)) console.log(i); //  0, 1, 2, "foo" } for (let i of iterable) console.log(i); // 3, 5, 7 

Chaque objet héritera de la méthode objCustom et chaque tableau héritera de la méthode arrCustom en les créant dans Object.prototype et Array.prototype. L'objet itérable héritera des méthodes objCustom et arrCustom en raison de l'héritage du prototype.

La boucle affiche uniquement les propriétés énumérées de l'objet itérable, dans l'ordre dans lequel elles ont été créées. Il n'imprime pas les valeurs 3, 5, 7 et bonjour car elles ne sont pas énumérables. Les noms des propriétés et des méthodes sont affichés, par exemple, arrCustom et objCustom.

La boucle est similaire à la précédente, mais utilise hasOwnProperty () pour vérifier si cette propriété de l'objet est la sienne ou héritée. Seules les propriétés propres sont affichées. Les noms 0, 1, 2 et foo n'appartiennent qu'à l'instance de l'objet (non hérité). Les méthodes arrCustom et objCustom ne sont pas sorties car elles sont héritées.

Cette boucle contourne l'itérable et affiche les valeurs de l'objet itérable qui sont définies dans la méthode d'itération, c'est-à-dire pas les propriétés de l'objet, mais les valeurs du tableau 3, 5, 7.

Noms de propriété calculés


La syntaxe de déclaration des objets et de leurs éléments prend en charge les noms de propriété calculés. Cela vous permet d'ajouter une expression entre crochets [] qui sera évaluée comme le nom de la propriété. Il ressemble aux littéraux de modèle.

Exemple de noms calculés:
 var a = () => "world"; var a = { ["a" + (10 - 6)]: { ["some" + "string"]: true, [10 + 20]: 10, [`hello ${a()}`]: a() } } 



Object.assign ()


La méthode Object.assign () est utilisée pour copier les valeurs de toutes ses propres propriétés énumérées d'un ou plusieurs objets source vers l'objet cible. Après la copie, il renvoie l'objet cible.

La méthode Object.assign () copie uniquement les propriétés énumérées et natives des objets source vers l'objet cible. Il utilise la méthode interne [[Get]] sur les objets source et la méthode interne [[Set]] sur l'objet cible, il appelle donc également les getters et setters. C'est pourquoi il attribue des propriétés au lieu de simplement copier ou définir de nouvelles propriétés. Ce comportement peut rendre la méthode inappropriée pour injecter de nouvelles propriétés dans le prototype si les objets source injectés contiennent des getters. Au lieu de cela, pour copier des prototypes de définitions de propriétés, y compris un signe de leur énumération, les méthodes Object.getOwnPropertyDescriptor () et Object.defineProperty () doivent être utilisées.

Les propriétés des types de chaîne et de symbole sont copiées.

En cas d'erreur, par exemple, lorsque la propriété n'est pas accessible en écriture, une exception TypeError est levée et l'objet cible reste inchangé.

Notez que la méthode Object.assign () ne lève pas d'exception si les valeurs initiales sont nulles ou non définies.

Exemple: clonage d'un objet
 var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } 

Exemple: fusion d'objets
 var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 },     . 


Paramètres de repos


La syntaxe des autres paramètres de la fonction vous permet de représenter un ensemble illimité d'arguments sous la forme d'un tableau.

Si le dernier argument de fonction nommé a un préfixe ..., il devient automatiquement un tableau avec des éléments de 0 à theArgs.length en fonction du nombre réel d'arguments passés à la fonction.

Syntaxe
 function(a, b, ...theArgs) { // ... } 


Un exemple d'utilisation de la syntaxe des paramètres restants:
 function name (a, b, ...c) {} name (0, 1, 2, 3,) 

Dans cet exemple, a = 0 b = 1 c [0] = 2 c [1] = 3
Si le paramètre restant n'est pas transmis, ce sera un tableau vide (contrairement aux paramètres ordinaires, il ne sera jamais indéfini).

Cette syntaxe peut être utilisée non seulement dans les arguments de fonction, mais également à d'autres endroits, par exemple, pour copier et combiner des tableaux:

 var a = [ 0, 1, 2 ]; var b = [ 3, 4, 5 ]; var c = [ ...a, ...b ]; // [ 0, 1, 2, 3, 4, 5 ] 


Paramètres par défaut


Les paramètres par défaut vous permettent de définir des paramètres de fonction formels sur des valeurs par défaut si la fonction est appelée sans arguments ou si le paramètre est explicitement transmis non défini.

En JavaScript, les paramètres d'une fonction qui ne reçoivent pas de valeurs lors de son appel prennent la valeur par défaut non définie. Cependant, dans certains cas, il peut être utile de définir une valeur par défaut différente. C'est dans de tels cas que les paramètres par défaut sont prévus.

La valeur par défaut n'est affectée à un paramètre formel que si, lors d'un appel de fonction, la valeur de ce paramètre n'a pas été transmise ou non définie a été explicitement transmise.

Un exemple d'utilisation des paramètres par défaut:
 function myFun(a=5) { return a*a; } console.log(myFun()); // 25 


Mission de restructuration


La syntaxe de déstructuration des affectations dans les expressions JavaScript vous permet de récupérer des données à partir de tableaux ou d'objets à l'aide d'une syntaxe similaire à la déclaration d'un tableau ou de littéraux dans un objet.

Les expressions de déclaration d'objets ou de tableaux fournissent un moyen simple de créer un ensemble de données homogènes. Lors de la création d'un tel package, vous avez la possibilité de l'utiliser de toutes les manières possibles. Vous pouvez également le retourner dans les fonctions.

L'une des principales façons d'utiliser l'affectation destructive est de lire la structure de données avec un seul opérateur, bien que vous puissiez trouver de nombreuses autres utilisations en plus de cela.

Exemple d'affectation destructrice:
 var a, b, rest; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2 [a, b, ...rest] = [1, 2, 3, 4, 5]; console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5] ({a, b} = {a:1, b:2}); console.log(a); // 1 console.log(b); // 2 

Vous pouvez voir plus d'exemples ici .

La carte


Map - Un objet contenant des paires clé-valeur et préservant l'ordre d'insertion. Toute valeur (objets et primitives) peut être utilisée comme clé.

Un exemple:
 var myMap = new Map(); var keyObj = {}, keyFunc = function () {}, keyString = "a string"; //   myMap.set(keyString, "value associated with 'a string'"); myMap.set(keyObj, "value associated with keyObj"); myMap.set(keyFunc, "value associated with keyFunc"); myMap.size; // 3 //   myMap.get(keyString); // "value associated with 'a string'" myMap.get(keyObj); // "value associated with keyObj" myMap.get(keyFunc); // "value associated with keyFunc" myMap.get("a string"); // "value associated with 'a string'" //   keyString === 'a string' myMap.get({}); // undefined,   keyObj !== {} myMap.get(function() {}) // undefined,   keyFunc !== function () {} 

Différence de la carte de l'objet:

  • Les clés d'objet sont des lignes et des symboles, tandis que toute valeur peut être une clé de carte, y compris des fonctions, des objets et des primitives.
  • Contrairement aux objets, les clés de la carte sont ordonnées. Ainsi, lors de l'itération Map, les clés sont retournées dans l'ordre d'insertion.
  • Vous pouvez facilement obtenir le nombre d'éléments dans une carte à l'aide de la propriété size, tandis que le nombre d'éléments dans un objet ne peut être déterminé que manuellement.
  • La carte est un objet itérable et peut être itéré directement, tandis que l'objet nécessite la réception manuelle de la liste des clés et de leur itération.
  • L'objet a un prototype et a donc un jeu de clés standard qui, s'il est imprudent, peut croiser vos clés. Depuis la sortie d'ES5, cela peut être changé en utilisant map = Object.create (null).
  • La carte peut avoir de meilleures performances en cas d'ajout ou de suppression fréquents de clés.

Propriétés et méthodes:

  • Map.prototype.size - Renvoie le nombre de paires clé / valeur sur une carte
  • Map.prototype.set (clé, valeur) - Ajoute la paire clé \ valeur transmise à la carte. Si la clé spécifiée existe déjà, elle sera remplacée par la nouvelle valeur.
  • Map.prototype.get (key) - Renvoie la valeur de la clé transmise. S'il n'y a pas de clé, alors undefined reviendra
  • Map.prototype.has (key) - Renvoie true si la clé transmise existe et false dans le cas contraire
  • Map.prototype.delete (key) - Supprime la paire clé / valeur spécifiée et renvoie true. Renvoie false si la clé n'existe pas.
  • Map.prototype.clear () - Supprime toutes les paires clé / valeur de la carte
  • Map.prototype.keys () - Retourne un itérateur de clés sur une carte pour chaque élément
  • Map.prototype.values ​​() - Retourne un itérateur de valeurs sur la carte pour chaque élément
  • Map.prototype.entries () - Retourne un itérateur du tableau [clé, valeur] sur la carte pour chaque élément


Ensemble


Vous permet d'enregistrer des valeurs uniques de tout type, à la fois des primitives et d'autres types d'objets.

Les objets Set représentent des collections de valeurs que vous pouvez parcourir dans l'ordre dans lequel les éléments sont insérés. La valeur d'un élément dans Set ne peut être présente que dans une seule instance, ce qui garantit son caractère unique dans la collection Set.

Ensemble de propriétés et de méthodes d'instance
  • size - Renvoie le nombre d'éléments dans l'objet Set.
  • add (value) - Ajoute un nouvel élément avec la valeur donnée à l'objet Set. Renvoie un objet Set.
  • clear () - Supprime tous les éléments de l'objet Set.
  • delete (value) - Supprime l'élément associé à la valeur et renvoie la valeur que (value) renverrait précédemment. has (value) retournera false plus tard.
  • entries () - Renvoie un nouvel objet Iterator qui contient un tableau de [valeur, valeur] pour chaque élément de l'objet Set dans l'ordre d'insertion. Il est stocké de manière similaire à l'objet Map, donc chaque entrée a la même valeur pour sa clé et sa valeur ici.
  • forEach (callbackFn [, thisArg]) - Appelle callbackFn une fois pour chaque valeur présente dans l'objet Set, dans l'ordre d'insertion. Si thisArg est spécifié pour thisEach, il sera utilisé comme valeur this pour chaque rappel.
  • has (value) - Retourne une valeur booléenne confirmant si l'élément avec la valeur donnée est présent ou non dans l'objet Set.
  • values ​​() - Renvoie un nouvel objet Iterator qui contient les valeurs de chaque élément de l'objet Set dans l'ordre d'insertion.

Utilisation de l'objet Set
 var mySet = new Set(); mySet.add(1); // Set { 1 } mySet.add(5); // Set { 1, 5 } mySet.add(5); // Set { 1, 5 } mySet.add("some text"); // Set { 1, 5, 'some text' } var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); //  o    ,      mySet.has(1); // true mySet.has(3); // false, 3     set mySet.has(5); // true mySet.has(Math.sqrt(25)); // true mySet.has("Some Text".toLowerCase()); // true mySet.has(o); // true mySet.size; // 5 mySet.delete(5); //  5  set mySet.has(5); // false, 5   mySet.size; // 4,     console.log(mySet); // Set {1, 'some text', Object {a: 1, b: 2}, Object {a: 1, b: 2}} 

Ensemble de dérivation
 //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet.keys()) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet.values()) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} //(key  value    ) for (let [key, value] of mySet.entries()) console.log(key); //  Set  Array var myArr = Array.from(mySet); // [1, "some text", {"a": 1, "b": 2}] //       HTML  mySet.add(document.body); mySet.has(document.querySelector("body")); // true //   Array  Set   mySet2 = new Set([1,2,3,4]); mySet2.size; // 4 [...mySet2]; // [1,2,3,4] //      var intersection = new Set([...set1].filter(x => set2.has(x))); //      var difference = new Set([...set1].filter(x => !set2.has(x))); //   set   forEach mySet.forEach(function(value) { console.log(value); }); // 1 // 2 // 3 // 4 



Cours


Les classes en JavaScript ont été introduites dans ECMAScript 2015 et sont du sucre syntaxique sur l'héritage de prototype en JavaScript. La syntaxe de classe n'introduit pas de nouveau modèle orienté objet, mais fournit un moyen plus simple et plus intuitif de créer des objets et d'organiser l'héritage.

Les classes sont en fait des «fonctions spéciales», donc tout comme vous définissez des fonctions (expressions de fonction et déclarations de fonction), vous pouvez définir des classes avec: des déclarations de classe et des expressions de classe.

La différence entre une déclaration de fonction et une déclaration de classe est qu'une déclaration de fonction est hissée, tandis qu'une déclaration de classe ne l'est pas. Par conséquent, vous devez d'abord déclarer votre classe et ensuite travailler avec elle, sinon une exception de type ReferenceError sera levée.

Déclaration de classe


La première façon de définir une classe consiste à utiliser une déclaration de classe. Pour ce faire, utilisez le mot clé class et spécifiez le nom de la classe (dans l'exemple, «myClass»).
 class myClass{ constructor(height, width) { this.height = height; this.width = width; } } 

La deuxième façon de définir une classe est l'expression de classe. Vous pouvez créer des expressions nommées et sans nom. Dans le premier cas, le nom de l'expression de classe se trouve dans la portée locale de la classe et peut être obtenu via les propriétés de la classe elle-même, et non son instance.
 //  var myClass = class { constructor(height, width) { this.height = height; this.width = width; } }; //  var myClass = class myClass { constructor(height, width) { this.height = height; this.width = width; } }; 

Les expressions de classe sont sujettes aux mêmes problèmes de levage que les déclarations de classe!

Les corps de déclaration de classe et les expressions de classe sont exécutés en mode strict.
Le mode strict modifie la syntaxe et le comportement du runtime.
Pour être plus précis, le mode strict se caractérise par les éléments suivants:
  • Convertir les erreurs en exceptions
  • des changements qui simplifient le calcul d'une variable dans certains cas d'utilisation de son nom;
  • , eval arguments;
  • , «» JavaScript;


  1. .
  2. .
  3. , , .
  4. ( ).
  5. , , . , .
  6. . .
  7. La syntaxe du système numérique octal est interdite.
  8. La définition de propriétés avec des valeurs primitives est interdite.

Simplification du travail avec les variables
Le mode strict simplifie la comparaison du nom de variable avec la place de sa définition dans le code.
  1. L'utilisation avec est interdite. Le problème avec est qu'au moment de l'exécution, tout nom à l'intérieur du bloc peut faire référence à une propriété de l'objet en cours de traitement ou à une variable dans le contexte environnant (ou même global) - il est impossible de le savoir à l'avance. Une alternative simple avec existe déjà - assigner l'objet à une variable avec un nom court puis accéder à la propriété souhaitée en tant que propriété de cette variable.
  2. eval () en mode strict n'ajoute pas de nouvelles variables au contexte environnant.
  3. Il est interdit de supprimer des noms simples.

Simplification de l'eval et des arguments
Le mode strict réduit le nombre de bizarreries dans le comportement des arguments et de l'eval, qui mélangent tous les deux une certaine quantité de magie en code normal. Donc, eval ajoute ou supprime des variables et modifie leurs valeurs, et la variable arguments peut vous surprendre avec ses propriétés indexées, qui sont des références (synonymes) pour les arguments des fonctions nommées.
  1. Les mots clés eval et les arguments ne peuvent pas être remplacés ou modifiés.
  2. Les champs de l'objet arguments ne sont pas associés aux arguments de la fonction nommée, mais sont leurs copies dupliquées des valeurs.
  3. La propriété arguments.callee n'est pas prise en charge. Dans le code normal, la propriété arguments.callee fait référence à la fonction elle-même, pour l'invocation dont l'objet arguments a été créé.

JavaScript «sécurisé»
Certains sites Web offrent aux utilisateurs la possibilité d'écrire du JavaScript qui sera exécuté sur le site au nom d'autres utilisateurs. Dans les navigateurs, JavaScript peut avoir accès à des informations privées, ce qui constitue une faille de sécurité dans JavaScript.
  1. La valeur transmise à la fonction car elle n'est pas convertie en objet en mode strict.
  2. Il n'est pas possible de «lancer» la pile JavaScript via les extensions ECMAScript de base.
  3. Dans les fonctions, la propriété arguments ne donne plus accès aux variables créées à l'intérieur de la fonction.

Vous pouvez consulter la spécification ECMAScript 5.1 pour en savoir plus sur le mode strict.
Et aussi la documentation de Mozilla.

Constructeurs


constructeur est une méthode spéciale utilisée pour créer et initialiser des objets créés à l'aide de la classe.
 class Student { constructor(name) { this.name = name; } } var robert = new Student('Robert'); console.log(robert.name); // Outputs 'Robert' 

Lors de la création de nouveaux objets à partir de la classe, constructor () sera lancé, ce qui est nécessaire pour initialiser les objets.

Il ne peut y avoir qu'une seule méthode dans une classe appelée constructeur. Si la classe contient plusieurs constructeurs, une exception SyntaxError sera levée.

Le super mot-clé peut être utilisé dans le constructeur pour appeler le constructeur de la classe parente.

Si vous n'avez pas défini de méthode constructeur, le constructeur par défaut sera utilisé.
Pour les classes de base, le constructeur par défaut est:
 constructor() {} 

Pour les classes dérivées, le constructeur par défaut est:
 constructor(...args) { super(...args); } 


Les méthodes


Syntaxe de déclaration de méthode:
 var obj = { property([parameters]) {}, get property() {}, set property(value) {}, * generator() {} }; 

Abréviation des méthodes de générateur
 var obj = { * g() { var index = 0; while(true) yield index++; } }; var it = obj.g(); console.log(it.next().value); // 0 console.log(it.next().value); // 1 


Toutes les définitions de méthode, à l'exception des méthodes de générateur, ne peuvent pas être des constructeurs et lèveront une TypeError si vous essayez de les instancier.

Noms de propriété calculés
 var obj = { ["foo" + 2](){ return 2; } console.log(obj.foo2()); // 2 }; 


Le mot clé statique définit des méthodes statiques pour une classe. Les méthodes statiques sont appelées sans instancier leur classe et ne peuvent pas être appelées sur des instances de la classe.

Syntaxe des getters et setters
 class Student { constructor(name) { this.name = name; } get Name() { return this.name; } set Name(newName) { if(typeof(newName) != "string") throw new Error("Name is not a string!"); else this.name = newName; // Robert } } var robert = new Student('robert'); robert.Name = "Robert"; console.log(robert.Name); 

  • setter - Requis pour la validation des paramètres écrits (comme dans l'exemple ci-dessus)
  • getter - Nécessaire pour obtenir des propriétés (bien qu'elles puissent être obtenues directement). Ne peut pas avoir d'arguments

Il n'y a pas d'encapsulation intégrée dans ES6, mais vous pouvez l'organiser vous-même. Par exemple, comme ceci:

 var Student = (function () { let privateProps = new WeakMap(); class Person { constructor(name, Age) { this.name = name; // public privateProps.set(this, {age: Age}); // private } get Age() { return privateProps.get(this).age; } set Age (newAge) { privateProps.set(this, {age: newAge}); } } return Person; })(); var robert = new Student('Robert', 19); robert.Age = 20; console.log(robert.Age); // 20 


Héritage


Le mot clé extend est utilisé dans les déclarations de classe et les expressions de classe pour créer une classe qui est un enfant d'une autre classe.

 class Person { constructor (age) { this.age = age; } sayAge () { return this.age; } } class Student extends Person { constructor (name, age) { super(age); this.name = name; } sayFull () { return `Hello my name is ${this.name} and I'm ${super.sayAge()} years old`; } } var robert = new Student("Robert", 19); console.log(robert.sayFull()); // Hello my name is Robert and I'm 19 years old 


Dans le constructeur, le mot clé super () est utilisé comme une fonction qui appelle le constructeur parent. Il doit être appelé avant le premier appel au mot-clé this dans le corps du constructeur. Le super mot-clé peut également être utilisé pour appeler des fonctions de l'objet parent.

Lorsque vous substituez les méthodes de la classe parent dans la classe enfant, les méthodes de la classe enfant seront appelées par défaut, mais vous pouvez appeler explicitement les méthodes de la classe parent à l'aide de la fonction super ().
 class obj { constructor(name){ this.name = name; } displayName(){ return this.name.length; } } undefined class obj_2 extends obj { constructor(name) { super(name); } displayName() { //     return [this.name, super.displayName()]; } } var Obj = new obj_2("obj_2"); console.log(Obj.displayName()); // Array [ "obj_2", 5 ] 


Extension d'objets en ligne avec extend
Cet exemple étend un objet Date en ligne.
 class myDate extends Date { constructor() { super(); } getFormattedDate() { var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; return this.getDate() + '-' + months[this.getMonth()] + '-' + this.getFullYear(); } } 


Promesse


L'objet Promise est utilisé pour les calculs différés et asynchrones.

La promesse peut être dans trois états:
  • en attente: état initial, non terminé et non rejeté.
  • (fulfilled): .
  • (rejected): .

(pending), (fulfilled), (), (rejected), . , then. ( , , .. « », , , DOM.)

Promise.prototype.then() Promise.prototype.catch() , , .
image

(promise)
Un objet Promise est créé à l'aide du nouveau mot clé et de son constructeur. Le constructeur Promise prend comme argument un argument appelé fonction exécuteur. Cette fonction doit accepter deux fonctions de rappel comme paramètres. La première (résolution) est appelée lorsque l'opération asynchrone s'est terminée avec succès et a renvoyé le résultat de son exécution en tant que valeur. Le deuxième rappel (rejet) est appelé lorsque l'opération a échoué et renvoie une valeur indiquant la raison de l'échec, le plus souvent un objet d'erreur.
 const myPromise = new Promise((resolve, reject) => { //   ,    : resolve(someValue); //   //  reject("failure reason"); //  }); 

Un objet fonction avec deux arguments, résoudre et rejeter, fait réussir la promesse; le second la rejette.

Pour fournir à la fonction la fonctionnalité de promesse, il vous suffit de lui renvoyer l'objet Promise.
 function myAsyncFunction(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xhr.statusText); xhr.send(); }); } 

Utilisation. puis les gestionnaires d'exécution et de rejet sont associés.

Les méthodes
  • Promise.all (itérable) - Attend que toutes les promesses soient exécutées ou rejetées pour l'une d'entre elles. Renvoie une promesse qui sera exécutée une fois toutes les promesses exécutées en itérable. Dans le cas où l'une des promesses est rejetée, Promise.all sera également rejetée.
  • Promise.allSettled (itérable) - Attend la fin de toutes les promesses reçues (à la fois l'exécution et le rejet). Renvoie une promesse qui est exécutée lorsque toutes les promesses reçues sont terminées (exécutées ou rejetées), contenant un tableau des résultats de l'exécution des promesses reçues.
  • Promise.race (itérable) - Attend l'exécution ou le rejet de l'une des promesses reçues. Renvoie une promesse qui sera exécutée ou rejetée avec le résultat de l'exécution de la première promesse exécutée ou rejetée de .iterable.
  • Promise.reject (reason) - Renvoie une promesse rejetée pour raison.
  • Promise.resolve (value) - Renvoie la promesse exécutée avec la valeur de résultat.

Promise Prototype
  • catch (onRejected) - Ajoute une fonction de rappel pour gérer le rejet d'une promesse, qui renvoie une nouvelle promesse faite avec la valeur transmise si elle est appelée, ou la valeur de résolution d'origine si la promesse est faite.
  • then (onFulfilled, onRejected) - Ajoute un gestionnaire de réalisation et de rejet de promesse, et renvoie une nouvelle promesse exécutée avec la valeur du gestionnaire appelé, ou la valeur d'origine si la promesse n'a pas été traitée (c'est-à-dire si le gestionnaire onFulfilled ou onRejected correspondant n'est pas une fonction).


Création d'une requête http asynchrone:
 const URL = "https://getfestivo.com/v1/holidays?api_key=f8f42551-eb66-49d2-bcba-b8e42727ddfb&country=US&year=2019"; //  API      function asyncHttpRequest (url) { return new Promise((resolve, reject) => { //  promise if (url == undefined) //     url reject(new Error("Expected url and received nothing")); else { resolve(() => { fetch(url).then((response) => { //   return response.json(); //    JSON   }).then((myJson) => { return(console.log(myJson)); //      }); }); } } );} asyncHttpRequest(URL).then((result) => result(), (error) => console.log(error)); 



Vous pouvez obtenir plus d'exemples et d'informations sur les promesses dans la documentation officielle , ainsi que dans la documentation de Mozilla .

Itérateurs


Le traitement de chaque élément d'une collection est une opération très courante. JavaScript offre plusieurs façons d'itérer sur une collection, d'une simple boucle for à map (), filter () et des compréhensions de tableau. Les itérateurs et les générateurs implémentent le concept d'énumération directement dans le cœur du langage et fournissent un mécanisme pour définir le comportement pour ... des boucles.

Un objet est un itérateur s'il peut accéder aux éléments de la collection un par un, tout en suivant sa position actuelle dans cette séquence. En JavaScript, un itérateur est un objet qui fournit une méthode next () qui renvoie l'élément suivant d'une séquence. Cette méthode renvoie un objet avec deux propriétés: done et value.

Une fois créé, l'objet itérateur peut être utilisé explicitement en appelant la méthode next ().

Iterable - Il s'agit d'un objet dont le contenu peut être itéré.
L'objet itérable diffère de l'objet non itérable en ce qu'il a une méthode spéciale qui renvoie un objet d'accès auquel un symbole spécial est utilisé: Symbol.iterator
 Iterable { [Symbol.iterator]() } 

L'objet qui renvoie la méthode est officiellement appelé un itérateur.
L'itérateur n'a qu'une seule méthode next ()
 Iterator { next(); } 

Qui retourne un objet (appelons-le itreratorResult) avec deux propriétés done et value
 IteratorResult { done, value } 

done indique s'il y a encore une valeur dans la séquence recherchée, et la valeur contient l'élément suivant de la séquence.


Après l'initialisation, la méthode next () peut être appelée pour accéder une par une aux paires clé-valeur de l'objet.

Un objet est itérable s'il définit une méthode d'énumération des valeurs, c'est-à-dire, par exemple, comment les valeurs sont énumérées dans la construction for..of. Certains types intégrés, tels que Array ou Map, sont itérables par défaut, tandis que d'autres types, tels que Object, ne le sont pas.

Pour être itérable, un objet doit implémenter la méthode itérateur, ce qui signifie qu'il (ou l'un des objets de la chaîne prototype) doit avoir une propriété appelée Symbol.iterator.

Voici à quoi ressemble l'itérateur standard:
 function makeIterator(array){ var nextIndex = 0; return { next: function(){ return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { done: true }; } } } 


Générateurs


Les générateurs sont un type spécial de fonction qui fonctionne comme une usine d'itérateurs. Une fonction devient un générateur si elle contient une ou plusieurs instructions yield et utilise la syntaxe function *.

Les générateurs sont un nouveau type de fonction qui peut suspendre son exécution et retourner un résultat intermédiaire et reprendre l'exécution plus tard.

Regardons une fonction régulière qui fait des calculs et renvoie un résultat:
 function myFunction (a) { a = a*2; a = a - 1; return a; } console.log(myFunction(5)); // 9 

Jetez maintenant un œil à une fonction de générateur similaire:
 function* generator(a) { a = a*2; yield a; a = a - 1; yield a; } var it = generator(5); console.log(it.next().value); // 10 console.log(it.next().value); // 9</i> 

Comme indiqué précédemment, les générateurs peuvent suspendre leur exécution et retourner un résultat intermédiaire. Cet exemple montre qu'au moment du premier appel, la fonction comme si elle suspend son exécution sur le premier point d'arrêt donne et renvoie le résultat de la première expression. Dans le deuxième appel, la fonction continue du point d'arrêt précédent et passe au suivant, renvoyant le résultat de l'expression suivante.

Les générateurs de fonctions fournissent un outil puissant pour écrire des fonctions séquentielles complexes.

Les générateurs calculent les résultats de leurs expressions de rendement à la demande, ce qui leur permet de travailler efficacement avec des séquences à haute complexité de calcul, voire des séquences infinies.

La méthode next () prend également une valeur qui peut être utilisée pour modifier l'état interne du générateur. La valeur passée à next () sera considérée comme le résultat de la dernière expression de rendement qui a interrompu le générateur.

Vous pouvez forcer le générateur à lever une exception en appelant sa méthode throw () et en transmettant la valeur de l'exception qui doit être levée en tant que paramètre. Cette exception sera levée à partir du contexte de pause actuel du générateur comme si l'instruction de rendement en pause actuelle était une instruction throw.

Si l'instruction yield ne se produit pas lors du traitement de l'exception levée, l'exception est transmise ci-dessus via l'appel throw (), et le résultat des appels suivants à next () sera la propriété done égale à true.

Les générateurs ont une méthode return (value) qui renvoie la valeur donnée et arrête le générateur.

Symbole


Le symbole est un type de données primitif dont les instances sont uniques et immuables.

Dans le runtime JavaScript, une valeur de «symbole» est créée en appelant la fonction Symbol (), qui crée dynamiquement une valeur anonyme et unique. La seule utilisation raisonnable consiste à enregistrer le caractère, puis à utiliser la valeur stockée pour créer la propriété de l'objet.

Lorsqu'un caractère est utilisé comme identificateur dans une affectation de propriété, la propriété (par exemple, un caractère) est anonyme; et aussi non dénombrable. Étant donné que la propriété n'est pas calculable, elle ne sera pas affichée dans la boucle "pour (... dans ...)" et, comme la propriété est anonyme, elle ne sera pas affichée dans le tableau de résultats "Object.getOwnPropertyNames ()". Cette propriété est accessible en utilisant la valeur initiale du symbole qui l'a créée, ou en itérant via le tableau de résultats «Object.getOwnPropertySymbols ()».


Vous pouvez donc créer une propriété de caractère:
 var user = { name: "Alex", [Symbol("password")]: "12hsK3I" } 

Pour obtenir un tableau d'objets de caractère, utilisez la propriété Object.getOwnPropertySymbols (obj);
Pour accéder n'importe où dans votre code, utilisez les méthodes Symbol.for () et Symbol.keyFor ().

Pour plus d'informations sur le type de données Sumbol, consultez la documentation officielle , ainsi que la documentation Mozilla.

Source: https://habr.com/ru/post/fr460741/


All Articles