Title: Pré-requis pour Three.js
Description: Ce que vous avez besoin de connaître pour comprendre ce site.
TOC: Pré-requis
Ces articles sont faits pour vous aider à apprendre comment utiliser three.js.
Ils supposent que :
* vous savez programmer en Javascript ;
* vous savez ce que c'est qu'un *DOM*, comment écrire du HTML, ainsi que créer des éléments *DOM*
en Javascript ;
* vous savez exploiter les
[modules es6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
que ce soit via le mot clef import ou via les balises `
```
Les chemins doivent être absolus ou relatifs. Ces derniers débutent toujours par `./` ou `../`,
ce qui est différent des autres balises telles que `
`, `` et les références css.
Davantage de détails se trouvent à la fin de [cet article](threejs-fundamentals.html).
## `document.querySelector` et `document.querySelectorAll`
Vous pouvez utiliser `document.querySelector` pour sélectionner le
premier élément qui correspond à un sélecteur CSS.
`document.querySelectorAll` retourne tous les éléments qui correspondent
à un sélecteur CSS.
## `onbody` n'est pas nécessaire
Beaucoup de pages vielles d'il y a 20 ans utilisent
Ce style est déprécié. Mettez vos scripts à la fin de la page.
```html
...
...
```
ou [utilisez la propriété `defer`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script).
## Connaître le fonctionnement des clôtures (*closures*)
```js
function a(v) {
const foo = v;
return function() {
return foo;
};
}
const f = a(123);
const g = a(456);
console.log(f()); // affiche 123
console.log(g()); // affiche 456
```
Dans le code ci-dessus, la fonction `a` créé une nouvelle fonction chaque fois qu'elle est appelée.
Cette fonction se *clôt* sur la variable `foo`. Voici [davantage d'information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures).
## Comprendre le fonctionnement de `this`
`this` est une variable passée automatiquement aux fonctions tout comme les arguments y sont passés.
Une explication simple est que quand vous appelez une fonction directement comme ceci :
somefunction(a, b, c);
`this` prendra la valeur `null` (dans le cas du mode *strict* ou d'un module) tandis que lorsque vous
appelez une fonction via l'opérateur `.` comme ceci :
someobject.somefunction(a, b, c);
`this` sera une référence vers `someobject`.
Ce fonctionnement peut dérouter lorsqu'il est combiné avec les fonctions de rappel (*callbacks*).
const callback = someobject.somefunction;
loader.load(callback);
Ceci ne fonctionne pas comme s'y attendrait une personne inexpérimentée parce que, quand
`loader.load` appelle la fonction de rappel, il n'utilise pas l'opérateur `.` et donc
par défaut `this` est null (à moins que loader le fixe arbitrairement à une valeur).
Si vous souhaitez que `this` se rapporte à `someobject` quand la fonction de rappelle
est activée, vous devez dire à Javascript de le lier à la fonction.
const callback = someobject.somefunction.bind(someobject);
loader.load(callback);
[Cet article peut aider à expliquer `this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this).
## Particularités d'ES5/ES6/ES7
### `var` est déprécié. Privilégiez l'usage de `const` et/ou `let`
Il n'y a **PLUS AUCUNE** raison d'utiliser `var`. L'utiliser est dorénavant considéré
comme une mauvaise pratique. Utilisez `const` si la variable n'est jamais réaffectée,
ce qui se passe dans la majorité des cas. Utilisez `let` dans le cas où la valeur change.
Cela aidera à éviter beaucoup de bogues.
### Utilisez `for(elem of collection)` jamais `for(elem in collection)`
`for of` est récent, `for in` est ancien. `for in` avait des problèmes résolus par `for of`
Voici un exemple où vous pouvez itérer au travers de toutes les paires clef/valeur
d'un objet :
```js
for (const [key, value] of Object.entries(someObject)) {
console.log(key, value);
}
```
### Utilisez `forEach`, `map`, et `filter` quand c'est utile
Les fonctions [`forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach),
[`map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map), et
[`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) ont
été ajoutées aux tableaux (*arrays*) et sont utilisés de manière assez intensives en JavaScript moderne.
### Utiliser l'affectation par décomposition (*destructuring*)
Soit l'objet `const dims = {width: 300, height: 150}`
ancien code
const width = dims.width;
const height = dims.height;
nouveau code
const {width, height} = dims;
### Utilisez les raccourcis pour la déclaration des objets
ancien code :
```js
const width = 300;
const height = 150;
const obj = {
width: width,
height: height,
area: function() {
return this.width * this.height
},
};
```
nouveau code :
```js
const width = 300;
const height = 150;
const obj = {
width,
height,
area() {
return this.width * this.height;
},
};
```
### Utilisez l'opérateur d'expansion `...`
L'opérateur d'expansion a de multiples usages. Voici un exemple :
```js
function log(className, ...args) {
const elem = document.createElement('div');
elem.className = className;
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
```
et un autre exemple :
```js
const position = [1, 2, 3];
somemesh.position.set(...position);
```
### Utilisez `class`
La syntaxe pour créer des objets au comportement de classe avant ES5
n'était connue que des programmeurs chevronnés. Depuis ES5, vous pouvez
à présent [utiliser le mot-clef `class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
qui est plus proche du style C++/C#/Java.
### Comprendre les accesseurs (*getters* et *setters*)
[Getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) et
[setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) sont
communs dans la plupart des langages modernes. La syntaxe de type `class`
de ES5 les rend plus faciles à employer qu'avant.
### Utilisez les fonctions fléchées (*arrow functions*) quand c'est approprié
Cela est particulièrement utile avec les fonctions de rappel (*callbacks*) et les promesses (*promises*).
```js
loader.load((texture) => {
// utiliser la texture
});
```
Les fonctions fléchées se lient avec `this`. Ainsi
```js
const foo = (args) => {/* code */};
```
est un raccourci pour
```js
const foo = (function(args) {/* code */}).bind(this));
```
### De l'utilisation des promesses ainsi que de async/await
Les promesses (*promises*) aident à l'utilisation de code asynchrone.
Async/await aident à l'utilisation des promesses.
Cela nécessiterait des développements trop long à détailler ici.
Toutefois, vous pouvez [en lire davantage sur les promesses ici](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
et sur [async/await ici](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await).
### Utilisez les gabarits de libellés (*template Literals*)
Les gabarits de libellés sont des chaînes de caractères délimitées par
des accents graves au lieu d'apostrophes doubles (*quotes*).
const foo = `this is a template literal`;
Les gabarits de libellés ont deux particularités. La première est d'être multi-ligne
```js
const foo = `this
is
a
template
literal`;
const bar = "this\nis\na\ntemplate\nliteral";
```
ainsi `foo` et `bar` ci-dessus sont similaires.
L'autre particularité est que vous pouvez sortir du mode chaîne et insérer des fragments
de code Javascript en utilisant `${javascript-expression}`.
C'est l'objet des gabarits. Par exemple :
```js
const r = 192;
const g = 255;
const b = 64;
const rgbCSSColor = `rgb(${r},${g},${b})`;
```
ou
```js
const color = [192, 255, 64];
const rgbCSSColor = `rgb(${color.join(',')})`;
```
ou
```js
const aWidth = 10;
const bWidth = 20;
someElement.style.width = `${aWidth + bWidth}px`;
```
# Apprenez les conventions de codage JavaScript
Alors que vous êtes libre de formater votre code comme vous le souhaitez, il
y a au moins une convention dont vous devez avoir connaissance. Les variables,
les noms de fonctions et de méthodes sont toutes en *lowerCasedCamelCase* (c'est
à dire que les mots formant les noms des entités sont collés les uns aux autres et leur première lettre
est en majuscule, les autres en minuscules à l'exception de la toute première lettre du nom qui
est également en minuscule -- NDT).
Les constructeurs, les noms des classes sont en *CapitalizedCamelCase* (
les mots formant les noms des entités sont collés les uns aux autres et leur première lettre
est en majuscule, les autres en minuscules -- NDT).
Si vous suivez cette règle, votre code ressemblera à la plupart des autres
écrits en JavaScript. Beaucoup de [linters](https://eslint.org), qui sont
des programmes vérifiant les erreurs dans votre code,
mettrons en évidence des erreurs si vous utiliser la mauvaise casse puisqu'en
suivant la convention ci-dessus ils sauront que ces lignes ci-dessous sont
mauvaises :
```js
const v = new vector(); // évidemment une erreur si toutes les classes commencent par une majuscule.
const v = Vector(); // évidemment une erreur si toutes les fonctions commencent par une minuscule.
```
# Envisagez l'utilisation de Visual Studio Code
Bien sûr, vous pouvez utiliser l'éditeur de votre choix mais, si vous ne l'avez pas
encore essayé, envisagez d'utiliser [Visual Studio Code](https://code.visualstudio.com/)
pour JavaScript et après l'avoir installé, [intégrez-y eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint).
Cela vous prendra quelques minutes à installer mais vous aidera grandement pour
trouver les bogues de votre JavaScript.
Quelques exemples
Si vous activez [la règle `no-undef`](https://eslint.org/docs/rules/no-undef)
alors VSCode via ESLint vous avertira de l'utilisation de nombreuses variables non définies.
Ci-dessous vous pouvez voir que nous avons écrit `doTheThing` à la place `doThing`.
`doThing` se retrouve souligné en rouge et un passage au dessus me dira que
c'est non défini. Une erreur est donc évitée.
Vous aurez des avertissements (*warnings*) en utilisant `THREE` donc ajoutez `/* global THREE */`
en haut de vos fichiers JavaScript pour notifier à eslint que `THREE` existe.
Ci-dessus, vous pouvez voir que eslint connaît la règle que les noms commençant par
une majuscule `UpperCaseNames` sont des constructeurs et vous devez donc utiliser `new`.
Une autre erreur évitée. C'est [la règle `new-cap` rule](https://eslint.org/docs/rules/new-cap).
Il y a [des centaines de règles que vous pouvez activer, désactiver ou personnaliser](https://eslint.org/docs/rules/).
Par exemple, précédemment nous avons indiquer que nous devions utiliser `const` et `let` à la place de `var`.
Ici nous avons utilisé `var` et nous avons été avertis que nous devions utiliser `let` ou `const`
Ici nous avons utilisé `let` mais comme la valeur de la variable ne change jamais, nous
nous voyons suggérer l'utilisation de `const`.
Bien sûr, si vous préférez conserver `var`, vous pouvez désactiver cette règle.
Comme écrit plus haut, nous préférons privilégier `const` et `let` à la place de `var`
puisqu'ils sont plus efficaces et évitent les bogues.
Pour les cas où vous avez vraiment besoin d'outrepasser une règle,
[vous pouvez ajouter un commentaire pour les désactiver](https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments)
pour une seule ligne ou une section de code.
# Si vous avez vraiment besoin d'assurer le support de vieux navigateurs, utilisez un transpileur
La plupart des navigateurs se mettent à jour automatiquement donc utiliser les subtilités
vues plus haut vous aiderons à être productif et éviter les bogues.
Ceci étant dit, si vous êtes dans un projet qui doit absolument supporter des
vieux navigateurs, il y a des [outils qui interpréterons votre code ES5/ES6/ES7
et le transpilent en code JavaScript pre-ES5](https://babeljs.io).