Bases de JavaScript pour les débutants

Le matériel, dont nous publions la traduction aujourd'hui, est dédié aux bases de JavaScript et est destiné aux programmeurs débutants. Il peut être considéré comme une petite référence aux constructions de base de JS. Ici, en particulier, nous parlerons du système de type de données, des variables, des tableaux, des fonctions, des prototypes d'objets et de certaines autres caractéristiques du langage.



Types de données primitifs


Les types de données primitifs suivants sont disponibles en JavaScript: number , boolean , string , undefined , null . Il convient de noter tout de suite que, lorsque vous travaillez avec des types de données primitifs, par exemple, avec des littéraux de chaîne, nous, même sans effectuer une conversion explicite, serons en mesure d'accéder à leurs méthodes et propriétés. Le point ici est que lorsque vous essayez d'effectuer de telles opérations, les littéraux sont automatiquement équipés du wrapper d'objet approprié.

▍ Numéros


JavaScript n'a qu'un seul type de nombre - ce sont les nombres à virgule flottante double précision. Cela conduit au fait que les résultats du calcul de certaines expressions sont arithmétiquement incorrects. Vous savez peut-être déjà qu'en JS la valeur de l'expression 0.1 + 0.2 pas 0.3 . En même temps, lorsque vous travaillez avec des entiers, de tels problèmes ne sont pas observés, c'est-à-dire 1 + 2 === 3 .

JavaScript a un objet Number , qui est un wrapper d'objet pour les valeurs numériques. Les objets de type Number peuvent être créés soit à l'aide d'une commande de la forme var a = new Number(10) , soit vous pouvez compter sur le comportement automatique du système décrit ci-dessus. Cela, en particulier, vous permet d'appeler des méthodes stockées dans Number.prototype telles Number.prototype sont appliquées aux littéraux numériques:

 (123).toString();  //"123" (1.23).toFixed(1); //"1.2" 

Il existe des fonctions globales conçues pour convertir les valeurs d'autres types en type numérique. C'est parseInt() , parseFloat() et la construction Number() , qui dans ce cas agit comme une fonction normale qui effectue la conversion de type:

 parseInt("1")       //1 parseInt("text")    //NaN parseFloat("1.234") //1.234 Number("1")         //1 Number("1.234")     //1.234 

Si, au cours de l'opération avec des nombres, quelque chose est obtenu qui n'est pas un nombre (lors de certains calculs ou lorsque vous essayez de convertir quelque chose en nombre), JavaScript ne générera pas d'erreur, mais présentera le résultat d'une telle opération comme la valeur NaN (Not-a-Number, pas un nombre). Afin de vérifier si une certaine valeur est NaN , vous pouvez utiliser la fonction isNaN() .

Les opérations arithmétiques JS fonctionnent de manière assez familière, mais vous devez faire attention au fait que l'opérateur + peut effectuer l'ajout de nombres et la concaténation de chaînes.

 1 + 1      //2 "1" + "1"  //"11" 1 + "1"    //"11" 

▍Chaînes


Les chaînes JavaScript sont des chaînes de caractères Unicode. Les littéraux de chaîne sont créés en entourant le texte à placer entre guillemets doubles ( "" ) ou simples ( '' ). Comme déjà mentionné, lorsque nous travaillons avec des littéraux de chaîne, nous pouvons compter sur l'encapsuleur d'objet correspondant, dont le prototype a de nombreuses méthodes utiles, parmi lesquelles substring() , indexOf() , concat() .

 "text".substring(1,3) //ex "text".indexOf('x')   //2 "text".concat(" end") //text end 

Les chaînes, comme les autres valeurs primitives, sont immuables. Par exemple, la méthode concat() ne modifie pas une chaîne existante, mais en crée une nouvelle.

▍Valeurs logiques


Le type de données logique dans JS est représenté par deux valeurs - true et false . Le langage peut convertir automatiquement diverses valeurs en un type de données logique. Ainsi, false, en plus de la valeur logique false , sont les valeurs null , undefined , '' (chaîne vide), 0 et NaN . Tout le reste, y compris les objets, représente de véritables significations. Au cours des opérations logiques, tout ce qui est considéré comme vrai est converti en true et tout ce qui est considéré comme faux est converti en false . Jetez un œil à l'exemple suivant. Conformément aux principes ci-dessus, une chaîne vide sera convertie en false et à la suite de cette exécution de code, la chaîne This is false arrivera à la console.

 let text = ''; if(text) { console.log("This is true"); } else { console.log("This is false"); } 

Les objets


Les objets sont des structures dynamiques constituées de paires clé-valeur. Les valeurs peuvent avoir des types de données primitifs, peuvent être des objets ou des fonctions.

Les objets sont plus faciles à créer à l'aide de la syntaxe littérale de l'objet:

 let obj = { message : "A message", doSomething : function() {} } 

Les propriétés d'un objet peuvent être lues, ajoutées, modifiées et supprimées à tout moment. Voici comment procéder:

  • Propriétés de lecture: object.name, object[expression] .
  • Écriture de données dans les propriétés (si la propriété en cours d'accès n'existe pas, une nouvelle propriété avec la clé spécifiée est ajoutée): object.name = value , object[expression] = value .
  • Suppression de propriétés: delete object.name , delete object[expression] .

Voici quelques exemples:

 let obj = {}; //    obj.message = "A message"; //    obj.message = "A new message"; //   delete object.message; //   

Les objets du langage sont implémentés sous forme de tables de hachage. Une simple table de hachage peut être créée à l'aide de la commande Object.create(null) :

 let french = Object.create(null); french["yes"] = "oui"; french["no"]  = "non"; french["yes"];//"oui" 

Si l'objet doit être rendu immuable, vous pouvez utiliser la commande Object.freeze() .

Pour parcourir toutes les propriétés d'un objet, vous pouvez utiliser la commande Object.keys() :

 function logProperty(name){ console.log(name); //  console.log(obj[name]); //   } Object.keys(obj).forEach(logProperty); 

▍Comparaison des valeurs des types et objets primitifs


Dans le travail pratique avec des valeurs primitives, vous pouvez, comme déjà mentionné, les percevoir comme des objets qui ont des propriétés et des méthodes, bien qu'ils ne soient pas des objets. Les valeurs primitives sont immuables, la structure interne des objets peut changer.

Variables


En JavaScript, les variables peuvent être déclarées à l'aide des mots clés var , let et const .

En utilisant le mot-clé var , vous pouvez déclarer une variable et, si nécessaire, l'initialiser avec une certaine valeur. Si la variable n'est pas initialisée, sa valeur n'est undefined . Les variables déclarées à l'aide du mot clé var ont une portée fonctionnelle.

Le mot clé let est très similaire à var , la différence est que les variables déclarées avec le mot clé let ont une portée de bloc.

Les variables déclarées à l'aide du mot clé const ont également une portée de bloc qui, étant donné que les valeurs de ces variables ne peuvent pas être modifiées, sera plus correctement appelée «constantes». Le mot-clé const , qui «fige» la valeur d'une variable déclarée en l'utilisant, peut être comparé à la méthode Object.freeze() , qui «fige» les objets.

Si une variable est déclarée en dehors d'une fonction, sa portée est globale.

Tableaux


Les tableaux en JavaScript sont implémentés à l'aide d'objets. Par conséquent, lorsque nous parlons de tableaux, nous discutons en fait d'objets similaires aux tableaux. Vous pouvez travailler avec des éléments de tableau à l'aide de leurs indices. Les indices numériques sont convertis en chaînes et utilisés comme noms pour accéder aux valeurs des éléments du tableau. Par exemple, une construction de la forme arr[1] similaire à une construction de la forme arr['1'] , et les deux donneront accès à la même valeur: arr[1] === arr['1'] . Conformément à ce qui précède, un tableau simple déclaré par la commande let arr = ['A', 'B', 'C'] est représenté comme un objet de la forme suivante:

 { '0': 'A', '1': 'B', '2': 'C' } 

La suppression d'éléments de tableau à l'aide de la commande de delete laisse des trous. Pour éviter ce problème, vous pouvez utiliser la commande splice() , mais elle fonctionne lentement, car, après la suppression d'un élément, elle déplace les éléments restants du tableau, les décalant en fait au début du tableau, vers la gauche.

 let arr = ['A', 'B', 'C']; delete arr[1]; console.log(arr); // ['A', empty, 'C'] console.log(arr.length); // 3 

Les méthodes de tableau facilitent l'implémentation de structures de données telles que les piles et les files d'attente:

 //  let stack = []; stack.push(1);           // [1] stack.push(2);           // [1, 2] let last = stack.pop();  // [1] console.log(last);       // 2 //  let queue = []; queue.push(1);           // [1] queue.push(2);           // [1, 2] let first = queue.shift();//[2] console.log(first);      // 1 

Les fonctions


Les fonctions en JavaScript sont des objets. Les fonctions peuvent être attribuées à des variables, stockées dans des objets ou des tableaux, transmises en tant qu'arguments à d'autres fonctions et renvoyées par d'autres fonctions.

Il existe trois façons de déclarer des fonctions:

  • Déclaration de fonction classique (déclaration de fonction ou déclaration de fonction).
  • L'utilisation d'expressions fonctionnelles (Function Expression), également appelées littéraux fonctionnels (Function Literal).
  • Utilisation de la syntaxe des fonctions fléchées (fonction flèche).

▍ Déclaration de fonction classique


Avec cette approche de déclaration de fonctions, les règles suivantes s'appliquent:

  • La fonction est le premier mot-clé d'une ligne de déclaration de function .
  • Un nom doit être attribué aux fonctions.
  • La fonction peut être utilisée dans le code avant sa déclaration en raison du mécanisme qui place la déclaration de la fonction au sommet de la portée dans laquelle elle est déclarée.

Voici à quoi ressemble une déclaration de fonction classique:

 function doSomething(){} 

▍ Expressions fonctionnelles


Lors de l'utilisation d'expressions fonctionnelles, les éléments suivants doivent être pris en compte:

  • Le mot clé de function n'est plus le premier mot d'une ligne de déclaration de fonction.
  • Un nom de fonction est facultatif. Il est possible d'utiliser à la fois des expressions fonctionnelles anonymes et nommées.
  • Les commandes pour appeler de telles fonctions doivent suivre les commandes pour leur déclaration.
  • Une telle fonction peut être lancée immédiatement après la déclaration en utilisant la syntaxe de IIFE (Immediateely Invoked Function Expression - immédiatement appelée expression de fonction).

L'expression fonctionnelle ressemble à ceci:

 let doSomething = function() {} 

▍ Fonctions flèches


Les fonctions fléchées, en fait, peuvent être considérées comme du «sucre syntaxique» pour créer des expressions fonctionnelles anonymes. Il convient de noter que ces fonctions n'ont pas leurs propres entités this et arguments . La déclaration de la fonction flèche ressemble à ceci:

 let doSomething = () = > {}; 

▍ Façons d'appeler des fonctions


Les fonctions peuvent être appelées de différentes manières.

Appel de fonction normale


 doSomething(arguments) 

Appel de fonction sous la forme d'une méthode objet


 theObject.doSomething(arguments) theObject["doSomething"](arguments) 

Appel de fonction constructeur


 new doSomething(arguments) 

Appel d'une fonction à l'aide de la méthode apply ()


 doSomething.apply(theObject, [arguments]) doSomething.call(theObject, arguments) 

Appel d'une fonction à l'aide de la méthode bind ()


 let doSomethingWithObject = doSomething.bind(theObject); doSomethingWithObject(); 

Les fonctions peuvent être appelées avec plus ou moins d'arguments que le nombre de paramètres spécifiés lors de leur déclaration. Au cours du travail de la fonction, les arguments "supplémentaires" seront simplement ignorés (bien que la fonction y aura accès), les paramètres manquants obtiendront la valeur undefined .

Les fonctions ont deux pseudo-paramètres: this et arguments .

▍ Mot-clé ceci


Le this représente le contexte d'une fonction. La valeur qu'il pointe dépend de la façon dont la fonction a été appelée. Voici les significations du mot this clé this fonction de la façon dont la fonction est appelée (elles sont décrites ci-dessus avec des exemples de code, dont les constructions sont utilisées ici):

  • L'appel de fonction habituel est window / undefined .
  • Un appel de fonction sous la forme d'une méthode objet est theObject .
  • Un appel de fonction sous la forme d'un constructeur est un nouvel objet.
  • Appel d'une fonction à l'aide de la méthode apply() - theObject .
  • Appel d'une fonction à l'aide de la méthode bind() - theObject .

▍ Arguments des mots clés


Le mot-clé arguments est un pseudo-paramètre qui donne accès à tous les arguments utilisés pour appeler la fonction. Il ressemble à un tableau, mais pas à un tableau. En particulier, il n'a pas de méthodes de tableau.

 function reduceToSum(total, value){ return total + value; } function sum(){ let args = Array.prototype.slice.call(arguments); return args.reduce(reduceToSum, 0); } sum(1,2,3); 

Une alternative au mot-clé arguments est la nouvelle syntaxe pour les paramètres restants. Dans l'exemple suivant, args est un tableau contenant tout ce qui a été transmis à la fonction lors de son appel.

 function sum(...args){ return args.reduce(reduceToSum, 0); } 

ReturnRetour opérateur


Une fonction qui n'a pas de return retour renverra undefined . En utilisant le mot-clé return , faites attention au fonctionnement du mécanisme d'insertion automatique des points-virgules. Par exemple, la fonction suivante renverra non pas un objet vide, mais une valeur undefined :

 function getObject(){ return { } } getObject() 

Afin d'éviter un problème similaire, le crochet ouvrant doit être placé sur la même ligne que la return :

 function getObject(){ return { } } 

Typage dynamique


JavaScript est un langage de frappe dynamique. Cela signifie que des valeurs spécifiques ont des types, mais pas des variables. Pendant l'exécution du programme, des valeurs de différents types peuvent être écrites dans la même variable. Voici un exemple de fonction qui fonctionne avec des valeurs de différents types:

 function log(value){ console.log(value); } log(1); log("text"); log({message : "text"}); 

Pour connaître le type de données stockées dans une variable, vous pouvez utiliser l'opérateur typeof() :

 let n = 1; typeof(n);   //number let s = "text"; typeof(s);   //string let fn = function() {}; typeof(fn);  //function 

Modèle d'exécution monothread


Le runtime JavaScript est monothread. Cela s'exprime notamment par l'impossibilité d'exécuter simultanément deux fonctions (si l'on ne tient pas compte des possibilités d'exécution de code asynchrone, que nous n'abordons pas ici). Le runtime a une soi-disant file d'attente d'événements, qui stocke une liste de tâches qui doivent être traitées. Par conséquent, pour un schéma d'exécution JS à un seul thread, le problème des verrous de ressources mutuelles n'est pas typique, par conséquent, le mécanisme de verrouillage n'est pas nécessaire ici. Cependant, le code entrant dans la file d'attente d'événements doit s'exécuter rapidement. En cas de surcharge de travail, dans l'application du navigateur, le thread principal, la page de l'application ne répondra pas aux actions de l'utilisateur et le navigateur proposera de fermer cette page.

Gestion des exceptions


JavaScript dispose d'un mécanisme de gestion des exceptions. Il fonctionne selon un principe assez habituel pour de tels mécanismes: le code qui peut provoquer une erreur est exécuté à l'aide de la construction try/catch . Le code lui-même est dans le bloc try , les erreurs sont traitées dans le catch .

Il est intéressant de noter que parfois JavaScript, en cas d'urgence, ne produit pas de messages d'erreur. Cela est dû au fait que JS n'a commis aucune erreur avant l'adoption de la norme ECMAScript 3.

Par exemple, dans le fragment de code suivant, une tentative de modification d'un objet «figé» échouera, mais aucune exception ne sera levée.

 let obj = Object.freeze({}); obj.message = "text"; 

Certaines des erreurs JS "silencieuses" apparaissent en mode strict, vous pouvez l'activer en utilisant la construction "use strict"; .

Système prototype


La base de ces mécanismes JS comme les fonctions constructeurs, la commande Object.create() , le mot class clé class , est basée sur un système prototype.
Prenons l'exemple suivant:

 let service = { doSomething : function() {} } let specializedService = Object.create(service); console.log(specializedService.__proto__ === service); //true 

Ici, pour créer un objet Object.create() , dont le prototype était de créer un objet de service , la commande Object.create() été utilisée. En conséquence, il s'avère que la méthode doSomething() peut être appelée en accédant à l'objet doSomething() . En outre, cela signifie que la propriété __proto__ de l'objet specializedService pointe vers un objet de service .

Créez maintenant un objet similaire en utilisant le mot class clé class :

 class Service { doSomething(){} } class SpecializedService extends Service { } let specializedService = new SpecializedService(); console.log(specializedService.__proto__ === SpecializedService.prototype); 

Les méthodes déclarées dans la classe Service seront ajoutées à l'objet Service.prototype . Les instances de la classe Service auront le même prototype ( Service.prototype ). Toutes les instances délégueront des appels de méthode à l'objet Service.prototype . Par conséquent, il s'avère que les méthodes ne sont déclarées qu'une seule fois, dans Service.prototype , après quoi elles sont "héritées" par toutes les instances de la classe.

▍ Chaîne prototype


Les objets peuvent être «héritiers» d'autres objets. Chaque objet possède un prototype dont les méthodes sont à sa disposition. Si vous essayez d'accéder à une propriété qui n'est pas dans l'objet lui-même, JavaScript commencera à la rechercher dans la chaîne de prototypes. Ce processus se poursuivra jusqu'à ce que la propriété soit trouvée ou jusqu'à ce que la recherche atteigne la fin de la chaîne.

À propos de la programmation fonctionnelle en JavaScript


En JavaScript, les fonctions sont des objets de première classe; le langage prend en charge le mécanisme de fermeture. Cela ouvre la voie à l'implémentation de techniques de programmation fonctionnelle dans JS. En particulier, nous parlons de la possibilité d'utiliser des fonctions d'ordre supérieur.

Une fermeture est une fonction interne qui a accès aux variables déclarées à l'intérieur de la fonction parent, même après l'exécution de la fonction parent.

Une fonction d'ordre supérieur est une fonction qui peut prendre d'autres fonctions comme arguments, renvoyer des fonctions ou faire les deux.

La programmation fonctionnelle dans JS est couverte dans de nombreuses publications. Si vous êtes intéressé, voici quelques documents sur ce sujet consacrés aux fonctions de première classe , à la composition , aux décorateurs , aux fermetures et à la lisibilité du code écrit dans un style fonctionnel.

Résumé


La puissance de JavaScript réside dans sa simplicité. La compréhension des mécanismes de base du langage permet au programmeur utilisant JS d'appliquer plus efficacement ces mécanismes et jette les bases de sa croissance professionnelle.

Chers lecteurs! Selon vous, quelles sont les caractéristiques de JavaScript que la plupart des débutants provoquent?

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


All Articles