Guide discord.js
Informations supplémentaires

Syntaxe ES6

Si vous avez utilisé JavaScript pendant seulement une (relativement) courte période ou n'avez pas beaucoup d'expérience avec, vous pourriez ne pas être conscient de ce qu'ES6 est et quelles caractéristiques bénéfiques cela inclut. Puisque ce guide est principalement pour les bots Discord, nous utiliserons un code discord.js comme exemple de ce que vous pourriez avoir par rapport à ce que vous pourriez faire pour bénéficier d'ES6.

Voici le code de démarrage que nous allons utiliser :

index.js
const { Client, Events, GatewayIntentBits } = require('discord.js'); 
const config = require('./config.json');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, () => {
	console.log('Ready!');
});

client.on(Events.InteractionCreate, (interaction) => {
	if (!interaction.isChatInputCommand()) return;

	const { commandName } = interaction;

	if (commandName === 'ping') {
		interaction.reply('Pong.');
	} else if (commandName === 'beep') {
		interaction.reply('Boop.');
	} else if (commandName === 'server') {
		interaction.reply('Guild name: ' + interaction.guild.name + '\nTotal members: ' + interaction.guild.memberCount);
	} else if (commandName === 'user-info') {
		interaction.reply('Your username: ' + interaction.user.username + '\nYour ID: ' + interaction.user.id);
	}
});

client.login(config.token);

Si vous l'aviez remarqué, ce code utilise déjà un peu d'ES6 ! Le mot-clé const et la déclaration de fonction fléchée (() => ...) est la syntaxe ES6, et nous recommandons de l'utiliser chaque fois que possible.

Quant au code ci-dessus, il y a quelques endroits où les choses pourraient être mieux faites. Regardons-les.

Littéraux de modèles

Si vous vérifiez le code ci-dessus, il fait actuellement des choses comme 'Guild name: ' + interaction.guild.name et 'Your username: ' + interaction.user.username, ce qui est parfaitement valide. C'est un peu difficile à lire, bien, et ce n'est pas trop amusant de taper constamment. Heureusement, il y a une meilleure alternative.

index.js
} else if (commandName === 'server') {
	interaction.reply('Guild name: ' + interaction.guild.name + '\nTotal members: ' + interaction.guild.memberCount); 
	interaction.reply(`Guild name: ${interaction.guild.name}\nTotal members: ${interaction.guild.memberCount}`); 
}
else if (commandName === 'user-info') {
	interaction.reply('Your username: ' + interaction.user.username + '\nYour ID: ' + interaction.user.id); 
	interaction.reply(`Your username: ${interaction.user.username}\nYour ID: ${interaction.user.id}`); 
}

Plus facile à lire et écrire ! Le meilleur des deux mondes.

Littéraux de modèles vs concaténation de chaînes

Si vous avez utilisé d'autres langages de programmation, vous pourriez être familier avec le terme "interpolation de chaîne". Les littéraux de modèles seraient l'implémentation de l'interpolation de chaîne de JavaScript. Si vous êtes familier avec la syntaxe heredoc, c'est très similaire ; cela permet l'interpolation de chaîne, ainsi que les chaînes multi-lignes.

L'exemple ci-dessous n'entrera pas trop dans les détails, mais si vous êtes intéressé de lire plus, vous pouvez en lire plus sur MDN.

const username = 'Sanctuary';
const password = 'pleasedonthackme';

function letsPretendThisDoesSomething() {
	return 'Yay for sample data.';
}

console.log('Your username is: **' + username + '**.'); 
console.log('Your password is: **' + password + '**.');
console.log(`Your username is: **${username}**.`); 
console.log(`Your password is: **${password}**.`);

console.log('1 + 1 = ' + (1 + 1)); 
console.log(`1 + 1 = ${1 + 1}`); 

console.log("And here's a function call: " + letsPretendThisDoesSomething()); 
console.log(`And here's a function call: ${letsPretendThisDoesSomething()}`); 

console.log('Putting strings on new lines\n' + 'can be a bit painful\n' + 'with string concatenation.'); 
console.log(`
	Putting strings on new lines
	is a breeze
	with template literals!
`);

Comme vous le remarquerez, les littéraux de modèle rendront également les espaces blancs à l'intérieur, y compris l'indentation ! Il y a des moyens contourner cela, que nous discuterons dans une autre section.

Vous pouvez voir comment cela rend les choses plus faciles et plus lisibles. Dans certains cas, cela peut même raccourcir votre code ! C'est quelque chose que vous voudrez exploiter autant que possible.

Fonctions fléchées

Les fonctions fléchées sont un raccourci pour les fonctions régulières, avec l'addition qu'elles utilisent un contexte this lexical à l'intérieur du leur. Si vous ne savez pas à quoi le mot-clé this référence, ne vous en souciez pas ; vous en apprendrez plus à mesure que vous progresserez.

Voici quelques exemples de façons dont vous pouvez bénéficier des fonctions fléchées par rapport aux fonctions régulières :

client.once(Events.ClientReady, function () {
	console.log('Ready!');
});
client.once(Events.ClientReady, () => console.log('Ready!')); 

client.on(Events.TypingStart, function (typing) {
	console.log(typing.user.tag + ' started typing in #' + typing.channel.name);
});
client.on(Events.TypingStart, (typing) => console.log(`${typing.user.tag} started typing in #${typing.channel.name}`)); 

client.on(Events.MessageCreate, function (message) {
	console.log(message.author.tag + ' sent: ' + message.content);
});
client.on(Events.MessageCreate, (message) => console.log(`${message.author.tag} sent: ${message.content}`)); 

var doubleAge = function (age) {
	return 'Your age doubled is: ' + age * 2;
};
const doubleAge = (age) => `Your age doubled is: ${age * 2}`; 

var collectorFilter = function (m) {
	return m.content === 'I agree' && !m.author.bot;
};
var collector = message.createMessageCollector({ filter: collectorFilter, time: 15_000 });
const collectorFilter = (m) => m.content === 'I agree' && !m.author.bot; 
const collector = message.createMessageCollector({ filter: collectorFilter, time: 15_000 });

Il y a quelques choses importantes que vous devez noter ici :

  • Les parenthèses autour des paramètres de fonction sont facultatives lorsque vous n'avez qu'un seul paramètre mais sont obligatoires sinon. Si vous pensez que cela vous confondra, il pourrait être bon d'utiliser des parenthèses.
  • Vous pouvez proprement mettre ce dont vous avez besoin sur une seule ligne sans accolades.
  • Omettre les accolades rendra les fonctions fléchées utilisent un retour implicite, mais seulement si vous avez une expression d'une seule ligne. Les variables doubleAge et filter en sont un bon exemple.
  • Contrairement à la déclaration function someFunc() { ... }, les fonctions fléchées ne peuvent pas être utilisées pour créer des fonctions avec une telle syntaxe. Cependant, vous pouvez créer une variable et lui donner une fonction fléchée anonyme comme valeur (comme vu avec les variables doubleAge et filter).

Nous ne couvrirons pas la portée lexicale this avec les fonctions fléchées ici, mais vous pouvez chercher si vous êtes toujours curieux. Là encore, si vous ne savez pas ce qu'est this ou quand vous en avez besoin, lire d'abord sur lexical this pourrait seulement vous confondre.

Déstructuration

La déstructuration est un moyen facile d'extraire des éléments d'un objet ou d'un tableau. Si vous n'avez jamais vu la syntaxe auparavant, cela peut être un peu confus, mais c'est simple à comprendre une fois expliqué !

Déstructuration d'objets

Voici un exemple courant où la déstructuration d'objets serait utile :

const config = require('./config.json');
const prefix = config.prefix;
const token = config.token;

Ce code est un peu verbeux et n'est pas très amusant à écrire chaque fois. La déstructuration d'objets simplifie cela, le rendant plus facile à lire et écrire. Jetez un œil :

const config = require('./config.json'); 
const prefix = config.prefix;
const token = config.token;
const { prefix, token } = require('./config.json'); 

La déstructuration d'objets prend ces propriétés de l'objet et les stocke dans des variables. Si la propriété n'existe pas, elle créera quand même une variable mais avec la valeur undefined. Donc, au lieu d'utiliser config.token dans votre méthode client.login(), vous utiliseriez simplement token. Et puisque la déstructuration crée une variable pour chaque élément, vous n'avez pas même besoin de cette ligne const prefix = config.prefix. Très cool !

De plus, vous pourriez faire ceci pour vos commandes :

client.on(Events.InteractionCreate, (interaction) => {
	const { commandName } = interaction;

	if (commandName === 'ping') {
		// ping command here...
	} else if (commandName === 'beep') {
		// beep command here...
	}
	// other commands here...
});

Le code est plus court et semble plus propre, mais ce ne devrait pas être nécessaire si vous suivez la partie gestionnaire de commandes du guide.

Vous pouvez également renommer les variables lors de la déstructuration, si nécessaire. Un bon exemple est lorsque vous extrayez une propriété avec un nom déjà utilisé ou qui entre en conflit avec un mot-clé réservé. La syntaxe est la suivante :

|// `default` est un mot-clé réservé
|const { default: defaultValue } = someObject;
|
|console.log(defaultValue);
|// 'Some default value here'

Déstructuration de tableaux

La syntaxe de déstructuration de tableaux est très similaire à la déstructuration d'objets, sauf que vous utilisez des crochets au lieu d'accolades. De plus, puisque vous l'utilisez sur un tableau, vous déstructurez les éléments dans le même ordre que le tableau. Sans déstructuration de tableaux, voici comment vous extrairiez les éléments d'un tableau :

|// en supposant que nous soyons dans une commande `profile` et que nous ayons une variable `args`
const name = args[0];
const age = args[1];
const location = args[2];

Comme le premier exemple avec la déstructuration d'objets, c'est un peu verbeux et pas amusant à écrire. La déstructuration de tableaux allège cette douleur.

const name = args[0]; 
const age = args[1];
const location = args[2];
const [name, age, location] = args; 

Une seule ligne de code qui rend les choses beaucoup plus propres ! Dans certains cas, vous pourriez ne même pas avoir besoin de tous les éléments du tableau (par exemple, lors de l'utilisation de string.match(regex)). La déstructuration de tableaux vous permet toujours d'opérer dans le même sens.

const [, username, id] = message.content.match(someRegex);

Dans cet extrait, nous utilisons une virgule sans fournir un nom pour l'élément du tableau dont nous n'avons pas besoin. Vous pouvez également lui donner un nom d'espace réservé (comme _match ou similaire) si vous préférez, bien sûr ; c'est entièrement une préférence à ce stade.

Le préfixe de trait de soulignement _ est une convention pour les variables inutilisées. Certaines règles de linting généreront une erreur ou un avertissement si vous définissez des identifiants sans les utiliser dans votre code mais ignorent les identifiants commençant par _.

var, let et const

Puisqu'il y a de nombreux articles là qui peuvent expliquer cette partie plus en profondeur, nous vous donnerons seulement un résumé et un lien d'article si vous choisissez d'en lire plus.

  1. Le mot-clé var est ce qui était (et peut toujours être) utilisé en JavaScript avant que let et const apparaissent. Il y a cependant de nombreux problèmes avec var, comme être de portée de fonction, des problèmes liés à l'hoisting et permettre la rédéclaration.
  2. Le mot-clé let est essentiellement le nouveau var ; il résout de nombreux problèmes que var a, mais son facteur le plus important serait qu'il est de portée de bloc et interdit la rédéclaration (pas la réaffectation).
  3. Le mot-clé const est pour donner aux variables une valeur constante qui ne peut pas être réaffectée. const, comme let, est aussi de portée de bloc.

La règle générale recommandée par ce guide est d'utiliser const partout où possible, let sinon, et éviter d'utiliser var. Voici un article utile si vous voulez en lire plus sur ce sujet.