Objets personalisés :
let personne = {
nom: 'John',
age: 30
}
Tiré de http://js-but1.codenestedu.fr/
string
: à ne pas confondre avec String
boolean
number
function
symbol
undefined
null
Date
Array
String
Objets personalisés :
let personne = {
nom: 'John',
age: 30
}
var
: portée fonctionnelle
let
: portée limitée au bloc
const
: portée limitée au bloc
Une const est initialisée à la déclaration et ne peut pas être réaffectée |
let person = ["John", "Doe", 25];
console.log(typeof person); /* Affichera "object" */
console.log(Array.isArray(person)); /* Affichera true */
console.log(person[0]); /* Affichera 'John' */
person.push("Tom");
console.log(person[3]); /* Affichera 'Tom' */
Objectif : Extraire les données d’un tableau ou d’un objet |
let person = ["John", "Doe", 25];
// Décomposition du tableau person
const [firstName, lastName, age] = person;
// Utilisation des variables extraites
console.log(firstName); // Output: 'John'
console.log(lastName); // Output: 'Doe'
console.log(age); // Output: 25
let person = {
firstName: "John",
lastName: "Doe",
age: 25
};
const { age, firstName } = person;
console.log(firstName); // Output: 'John'
console.log(age); // Output: 25
let fruits = ["Apple", "Banana", "Orange", "Grapes"];
// Utilisation de l'opérateur de reste dans la décomposition
const [firstFruit, ...restOfFruits] = fruits;
console.log(firstFruit); // Output: 'Apple'
console.log(restOfFruits); // Output: ['Banana', 'Orange', 'Grapes']
Identique au Java
const person = ["John", "Doe", 25];
for (let i = 0; i < person.length; i++) {
console.log(person[i]);
}
Identique au Java
let randomNumber;
let foundOdd = false;
while (!foundOdd) {
randomNumber = Math.floor(Math.random() * 100) + 1;
console.log(`Nombre aléatoire : ${randomNumber}`);
if (randomNumber % 2 !== 0) {
console.log('Nombre impair trouvé');
foundOdd = true;
}
}
const person = ["John", "Doe", 25];
for (let x of person) {
console.log(x);
}
Contrairement au for classique, on ne récupère pas l’index ici |
La fonction passée en paramètre implémente le comportement attendu à chaque tour de boucle.
const persons = ["John", "Doe", 25];
persons.forEach(function(person, index, tab) {
console.log(`Index ${index}, value ${person}, array ${tab}`)
});
Cette boucle permet d’itérer sur les attributs d’un objet (mais fonctionne également sur les tableaux)
let oldCar = {
make: 'Toyota',
model: 'Tercel',
year: '1996'
};
for (let key in oldCar) {
console.log(`${key} --> ${oldCar[key]}`);
}
Fonction classique (1 seule ligne de code)
function add(a, b) {
return a + b;
}
Fonction fléchée équivalente
const add = (a, b) => a + b;
Fonction classique (Plusieurs lignes)
function min(a,b){
if ( a < b )
return a;
else
return b;
}
Fonction fléchée équivalente
const min = (a,b)=>{
if ( a < b )
return a;
else
return b;
}
Fonction fléchée sans paramètre
class Truc {
parler = () =>{
console.log("Je suis une méthode, et je parle");
}
}
const truc = new Truc();
truc.parler();
Fonction fléchée avec paramètre
class Truc {
crier = (mot) =>{
console.log(`Je suis une méthode et je crie : ${mot}`);
}
}
const truc = new Truc();
truc.crier("Bonjour !");
this
?Les fonctions fléchées n’ont pas leur propre contexte this , elles héritent du contexte dans lequel elles sont définies. |
this
? class Counter {
constructor() {
this.count = 0;
this.startCounting();
}
startCounting() {
// Le contexte à this de la classe counter est perdu.
setInterval(function() {
this.increment(); // <- Cette ligne causera une erreur
}, 1000);
}
increment() {
this.count++;
console.log("Count:", this.count);
}
}
const counter = new Counter();
this
?class Counter {
constructor() {
this.count = 0;
this.startCounting();
}
startCounting() {
// Utilisation de setInterval avec une fonction fléchée
setInterval(() => {
this.increment(); // <- Fonctionne correctement
}, 1000);
}
increment() {
this.count++;
console.log("Count:", this.count);
}
}
const counter = new Counter();
cf fonctionnement de la boucle forEach
:
const someFunction = (callback) => {
console.log("Dans la fonction someFunction");
callback(); // Appel de la fonction callback
};
const callback = () => {
console.log("Dans la fonction callback");
};
someFunction(callback); // Passer la fonction callback comme "paramètre" à someFunction
push()
et pop()
:
let fruits = ['pomme', 'orange'];
fruits.push('banane'); // Ajoute 'banane' à la fin
const dernierFruit = fruits.pop(); // Retourne et retire 'banane'
unshift()
et shift()
:
let fruits = ['orange', 'banane'];
fruits.unshift('pomme'); // Ajoute 'pomme' au début
let premierFruit = fruits.shift(); // Retourne et retire 'pomme'
concat()
:
let fruits = ['pomme', 'orange'];
let legumes = ['carotte', 'brocoli'];
let aliments = fruits.concat(legumes); // ['pomme', 'orange', 'carotte', 'brocoli']
//ou avec la décomposition
aliments = [...fruits, ...legumes];
indexOf()
et lastIndexOf()
:
let fruits = ['pomme', 'orange', 'banane', 'fraise', 'banane'];
let indexBanane = fruits.indexOf('banane'); // 2
let lastIndexBanane = fruits.lastIndexOf('banane'); // 4
Remplir un tableau :
Array(5).fill(Math.random(10));
Remplir une matrice :
Array.from({ length: 5 }, function () {
return Array(5).fill(Math.random(10));
});
Principales caractéristiques :
Liste de valeurs uniques
Pas d'indexation
Itérable
Taille dynamique
add()
:
let mySet = new Set();
mySet.add(1); // 1
delete()
:
let mySet = new Set();
mySet.add(1); // Set()
mySet.delete(1); // true
has()
:
let mySet = new Set();
mySet.add(1); // Set()
mySet.has(1); // true
mySet.delete(1); // true
mySet.has(1); // false
size()
:
let mySet = new Set();
mySet.add(1); // Set()
mySet.size(); // 1
Itération :
let mySet = new Set();
mySet.add(1); // Set()
mySet.add(2); // Set()
for (let item of mySet) {
console.log(item); // 1, 2
}
// où
mySet.forEach(value => console.log(value));
Principales caractéristiques :
Liste de clés uniques, quel que soit leur type
Pas d'indexation
Itérable
Taille dynamique
set()
:
let sayings = new Map();
sayings.set("dog", "woof"); // Map()
sayings.set("dog", "waf"); // Modifie la valeur de la clé "dog"
delete()
:
let sayings = new Map();
sayings.set("dog", "woof"); // Map()
sayings.delete("dog"); // true
has()
:
let sayings = new Map();
sayings.set("dog", "woof"); // Map()
sayings.has("dog"); // true
size()
:
let sayings = new Map();
sayings.set("dog", "woof"); // Map()
sayings.size(); // 1
Itération :
for (let [key, value] of sayings) {
console.log(key + " goes " + value);
}
// ou
sayings.forEach((value, key) => {
console.log(key + " goes " + value);
})
Array si on veut :
Liste ordonnée
Accéder aux objets via leur indice
Méthodes spécifiques (push, pop, slice, etc.)
Eléments dupliqués
Set si on veut :
Valeurs uniques
Pas de clefs/valeurs associées
Recherche fréquente d’une valeur dans la liste
Map si on veut :
Clefs/valeurs
Opérations fréquentes de recherche/modification d’une valeur via sa clef
Une classe se déclare presque comme en Java :
class Personne {
static nombreTotalPersonnes = 0;
constructor(nom, prenom){
this.nom = nom;
this.prenom = prenom;
Personne.nombreTotalPersonnes++;
}
identite = () => {
console.log(`La personne s'appelle ${this.prenom} ${this.nom}`);
}
static afficherNombreTotalPersonnes = () => {
console.log(`${Personne.nombreTotalPersonnes} instances de Personne ont été créées`);
}
}
Elle se manipule comme ceci :
let personne1 = new Personne("Valjean", "Jean");
let personne2 = new Personne("Trouillefou", "Clopin");
personne1.identite(); (1)
Personne.afficherNombreTotalPersonnes();(2)
1 | Output : 'La personne s’appelle Jean Valjean' |
2 | Output : 2` |
class MyClass {
#privateAttribute = "0";
#privateMethod = () => {
this.#privateAttribute++;
console.log("+ méthode privée");
}
publicMethod = () => {
console.log("méthode publique");
this.#privateMethod(); /* Appel de la méthode privée */
console.log(this.#privateAttribute); /* Accès à l'attribut privé */
}
}
const myObject = new MyClass();
myObject.publicMethod();(1)
myObjects.privateMethod();(2)
1 | Output : méthode publique + méthode privée |
2 | Erreur |
Window
Quelques proprietés :
window.innerHeight
→ Hauteur de la fenêtre
window.innerWidth
→ Largeur de la fenêtre
window.location
→ URL de la page
window.navigator
→ Informations sur le navigateur
window.screen
→ Informations sur l’écran
window.document
→ Document HTML de la page
Document
Tous les éléments du document HTML d’une page web sont représentés par des objets Javascript. Ceux-ci sont structurés sous forme d’un arbre qui reflète la structure du document HTML. |
Document
Comment accéder aux noeuds ?
<body>
<h1>Titre</h1>
<div id="images">
<img src="http://urlz.fr/TnT">
<img src="http://urlz.fr/TnU">
</div>
<div id="commentaires">
<div class="commentaire">Très belle image</div>
<div>
<script src="src.js"></script>
</body>
Document
<body>
<h1>Titre</h1>(1)
<div id="images">(2)
<img src="http://urlz.fr/TnT">(3)
<img src="http://urlz.fr/TnU">
</div>
<div id="commentaires">
<div class="commentaire">Très belle image</div>
<div>
<script src="src.js"></script>
</body>
1 | document.body.children[0] |
2 | document.body.children[1] |
3 | document.body.children[1].children[0] |
ELEMENT_NODE : <p>
ou <div>
par exemple
TEXT_NODE : Le texte actuel d’un élément
PROCESSING_INSTRUCTION_NODE
COMMENT_NODE : Un noeud Comment
DOCUMENT_NODE : Un noeud Document
DOCUMENT_TYPE_NODE : Un noeud DocumentType
(<!DOCTYPE html> par exemple)
DOCUMENT_FRAGMENT_NODE : Un noeud DocumentFragment
<body>
<h1 id ="titre">Titre</h1>
<p id = "paragraphe1"> Bonjour </p>
<div id="images">
<img src="https://www.iut.fr/info-2.jpg">
<img src="https://www.iut.fr/cours.jpeg">
</div>
<div id="uneDiv">
<p>Images de l'IUT<p>
<div>
</body>
let node = document.getElementById("titre");
console.log(node.nodeType);
Output : Element node
<body>
<h1 id ="titre">Titre</h1>
<p id = "paragraphe1"> Bonjour </p>
<div id="images">
<img src="https://www.iut.fr/info-2.jpg">
<img src="https://www.iut.fr/cours.jpeg">
</div>
<div id="uneDiv">
<p>Images de l'IUT<p>
<div>
</body>
let node = document.getElementById("uneDiv").firstElementChild.firstChild;
console.log(node.nodeType);
Output : Text node
<body>
<h1 id ="titre">Titre</h1>
<p id = "paragraphe1"> Bonjour </p>
<div id="images">
<img src="https://www.iut.fr/info-2.jpg">
<img src="https://www.iut.fr/cours.jpeg">
</div>
<div id="uneDiv">
<p>Images de l'IUT<p>
<div>
</body>
let node = document.getElementById("uneDiv").firstElementChild.firstElementChild;
console.log(node.nodeType);
Erreur ! |
Pour manipuler simplement du texte on utilisera : |
let valeur = document.getElementById("titre").textContent;
console.log(valeur); // le texte "Titre"
document.getElementById("titre").textContent = "Le titre a changé";
Trois méthodes principales :
let elementUnique = document.getElementById("personName")
let htmlCollection = document.getElementsByTagName("div")(1)
1 | Tag = balise html |
let nodeListe = document.querySelectorAll("un-selecteur-css")
let div = document.createElement('div');
let paragraphe = document.createElement('p');
let newtext = document.createTextNode("Valjean");
paragraphe.appendChild(newText);
div.appendChild(paragraphe);
let otherParagraphe = document.createElement('p');
let otherText = document.createTextNode("Bonjour");
otherParagraphe.appendChild(otherText);
div.insertBefore(otherParagraphe, paragraphe);
div.remove();
<body>
<div>
<p>Bonjour</p>
<p>Valjean</p>
</div>
</body>
<body>
<div>
<a href="www.google.com">Un lien</a>
<p id="personName">Georges</p>
<img src="petitChat.png"/>
</div>
</body>
let node = document.getElementById("personName");
console.log(node.parentNode)(1)
console.log(node.previousSibling)(2)
console.log(node.nextSibling)(3)
console.log(node.childNodes)(4)
<body>
<div>
<a href="www.google.com">Un lien</a>
<p id="personName">Georges</p>
<img src="petitChat.png"/>
</div>
</body>
let node = document.getElementById("personName");
console.log(node.parentNode)(1)
console.log(node.previousSibling)(2)
console.log(node.nextSibling)(3)
console.log(node.childNodes)(4)
1 | Output : <div> |
<body>
<div>
<a href="www.google.com">Un lien</a>
<p id="personName">Georges</p>
<img src="petitChat.png"/>
</div>
</body>
let node = document.getElementById("personName");
console.log(node.parentNode)(1)
console.log(node.previousSibling)(2)
console.log(node.nextSibling)(3)
console.log(node.childNodes)(4)
1 | Output : <div> |
2 | Output : <a> |
<body>
<div>
<a href="www.google.com">Un lien</a>
<p id="personName">Georges</p>
<img src="petitChat.png"/>
</div>
</body>
let node = document.getElementById("personName");
console.log(node.parentNode)(1)
console.log(node.previousSibling)(2)
console.log(node.nextSibling)(3)
console.log(node.childNodes)(4)
1 | Output : <div> |
2 | Output : <a> |
3 | Output : <img> |
<body>
<div>
<a href="www.google.com">Un lien</a>
<p id="personName">Georges</p>
<img src="petitChat.png"/>
</div>
</body>
let node = document.getElementById("personName");
console.log(node.parentNode)(1)
console.log(node.previousSibling)(2)
console.log(node.nextSibling)(3)
console.log(node.childNodes)(4)
1 | Output : <div> |
2 | Output : <a> |
3 | Output : <img> |
4 | Output : NodeList → length = 0 |
value
:
Propriété spécifique pour les éléments de formulaire tels que les inputs, les textareas, etc
Permet de définir ou d’obtenir la valeur actuelle de l’élément de formulaire
textContent
:
Propriété spécifique aux nœuds DOM qui représentent des éléments (comme <div>
, <p>
, <span>
, etc.)
Renvoie le contenu textuel de l’élément et de tous ses descendants sous forme de texte brut
Utilisée pour récupérer ou définir le contenu textuel visible d’un élément, en ignorant tout balisage HTML présent à l’intérieur
nodeValue
:
Propriété générale pour tous les nœuds DOM, pas seulement les éléments de formulaire
Permet d’accéder ou de définir la valeur du nœud DOM, qui peut être du texte, des commentaires, etc
let bouton = document.getElementById("bouton");
bouton.addEventListener("click", maFonctionDeGestionEvenement);
function maFonctionDeGestionEvenement(event){
console.log(event);
}
let bouton = document.getElementById("bouton");
bouton.addEventListener("click", function (event){
console.log(event);
});
let bouton = document.getElementById("bouton");
bouton.addEventListener("click", (event) => {
console.log(event);
});
let div = document.getElementById("maDiv");
div.addEventListener("click", (event) => {
bouton.removeEventListener("click", maFonctionDeGestionEvenement);(1)
});
1 | Lorsque les fonctions ne sont pas nommées, la méthodologie est différente ! |
this
?const element = document.getElementById("paragraphe");
const name = 'Something Good';
const onclick = function () {
console.log(name); /* 'Something Good' */
this.style.color = 'red'; (1)
};
element.addEventListener('click', onclick, false);
1 | OK : Ici this référence le paragraphe cliqué |
this
?const element = document.getElementById("paragraphe");
const name = 'Something Good';
const onclick = (event) => {
console.log(name); /* 'Something Good' */
this.style.color = 'red'; (1)
event.target.style.color = 'green'; (2)
};
element.addEventListener('click', onclick, false);
1 | KO : this référence l’objet windows et pas le paragraphe |
2 | OK : Event est là pour récupérer l’élément ayant généré l’évènement |
this
?class Something {
constructor() {
this.name = 'Something Good';
}
maMethodeFlechee = (event) =>{
console.log(`${this.name}`); (1)
event.target.style.color = 'green';
}
}
const something = new Something();
const element = document.getElementById("paragraphe");
element.addEventListener('click', something.maMethodeFlechee);
1 | OK : this est l’instance de Something car nous sommes dans une fonction fléchée |
this
?class Something {
constructor() {
this.name = 'Something Good';
}
maMethodeClassique(){
console.log(`${this.name}`); (1)
this.style.color = 'red'; (2)
}
}
const something = new Something();
const element = document.getElementById("paragraphe");
element.addEventListener('click', something.maMethodeClassique);
1 | KO : Impossible car c’est une fonction nommée, qui a son propre contexte |
2 | OK : this représente bien le paragraphe cliqué |
Evénement synthétique = événement qui n’est pas généré par le navigateur (mais par le code) |
event
personnaliséconst event = new Event('less-custom-event');
const customEvent =
new CustomEvent('most-custom-event', {});
event
personnalisélet event = new CustomEvent('my-custom-event', {
detail: "Les livres sont des amis froids et sûrs."
});
const user = {
prenom: "Jean",
nom: "Valjean"
}
let event = new CustomEvent('my-custom-event', { detail: user });
document.dispatchEvent(event);
document.addEventListener('my-custom-event', (event) => {
console.log(event.detail); (1)
});
1 | Output : {prenom: 'Jean', nom: 'Valjean'} |
export default class Utilisateur {
#nom;
#prenom;
constructor(nom, prenom) {
this.#nom = nom;
this.#prenom = prenom;
}
afficherNomComplet = () => {
console.log(`Nom complet: ${this.nom} ${this.prenom}`);
}
}
import NomDeVotreChoix from './Utilisateur.js';
// Création d'une instance de la classe Utilisateur
const utilisateur = new NomDeVotreChoix("Doe", "John");
// Utilisation des méthodes de la classe Utilisateur
utilisateur.afficherNomComplet();
export class Utilisateur {
// Même code que précédemment
}
import { Utilisateur } from './Utilisateur.js';
const utilisateur = new Utilisateur("Doe", "John");
// Utilisation des méthodes de la classe Utilisateur
utilisateur.afficherNomComplet();
<body>
<p> du texte </p>
<script>
//du code JS
</script>
</body>
Pas bien ! |
<body>
<p> du texte </p>
<script src="chemin/vers/votre/fichier.js"></script>
<script src="chemin/vers/votre/autreFichier.js"></script>
</body>
Mieux… |
<body>
<button id="b1">Créer un utilisateur</button>
<script type="module" src="app.js"></script>
</body>
Très bien ! |
{
"person": {
"name": "John Doe",
"age": 30,
"city": "New York",
"isStudent": false,
"courses": ["Math", "History"]
}
}
const person = {
name: 'John',
age: 30,
city: 'New York'
};
const jsonString = JSON.stringify(person);
console.log(jsonString); (1)
1 | Output : {name: 'John', age: 30, city: 'New York'} |
const jsonString = '{"name":"John","age":30,"city":"New York"}';
const person = JSON.parse(jsonString);
console.log(person);(1)
1 | Output : {"name":"John","age":30,"city":"New York"} |
const monImage = document.querySelector('img');
let maRequete = new Request('IUT.png');
fetch(maRequete)(1)
.then(reponse => {
if (!reponse.ok) {(2)
throw new Error(`erreur HTTP! statut: ${reponse.status}`);
}
return reponse.blob();(3)
})
.then(blob => {
let URLobjet = URL.createObjectURL(blob); (4)
monImage.src = URLobjet;
})
.catch(error => console.error(error));
1 | La requête part vers le serveur distant, lorsqu’elle revient, alors then est executé |
2 | Si la réponse est valide (code 200), alors on la traite, sinon on lève une erreur |
3 | On récupère le contenu de la requête, qu’on manipulera ensuite |
4 | A cette étape, on transforme le "blob" pour l’utiliser dans notre html |
const myList = document.querySelector('ul');
const myRequest = new Request('foot.json');
fetch(myRequest)
.then((response) => response.json()) (1)
.then((data) => {
for (const v of data) {(2)
const listItem = document.createElement('li');
let text = `${v.vainqueur} a gagné la coupe en ${v.annee}`;(3)
listItem.textContent = text
myList.appendChild(listItem);
}
})
.catch(error => console.error(error));
1 | On peut récupérer de cette façon le json associé à la requête |
2 | JSON est un format qui permet de boucler sur le contenu (un Array) |
3 | Il faut avoir lu l’API pour savoir comment se nomment les attributs (ici "vainqueur" et "année") |
const apiURL = 'fruits&legumes.com';
const endPoint = 'findMe';
const type = 'legume';
const couleur = 'vert';
let apiEndpoint =
`https://${apiURL}/${endPoint}?type=${type}&couleur=${couleur}`
console.log(apiEndpoint)(1)
1er paramètre : ?nomDuParametre=
Paramètres suivants : &nomDuParametre=
GET
: Récupérer des informations sur une ressource existante
POST
: Créer une nouvelle ressource sur le serveur distant
PATCH
: Mettre à jour une ressource existante
const maFonctionAsynchrone = async () => { (1)
try {
let response = await fetch(url, options);(2)
let result = await response.json();(3)
console.log(result);
} catch (error) {
console.error('Error:', error);
}
}
1 | Utilisation du mot-clef async dans la déclaration de la fonction |
2 | Attend que la réponse arrive avant d’exécuter la ligne du dessous |
3 | Lit le corps de la réponse au format JSON |
Soit une classe :
class Animal {
constructor(name) {
this.name = name;
}
noise () {
console.log(`I am an animal of type : `)
}
}
class Bird extends Animal { (1)
constructor(name) {
super(name); (2)
this.type = 'Bird';
}
noise = () => {
super.noise(); (3)
console.log(`${this.type}, I tweet `);(4)
}
}
1 | Mot-clef extends |
2 | super() appelle le constructeur de la classe mère |
3 | super.uneFonction() appelle une fonction de la classe mère |
4 | Output : I am an animal of type Bird, I tweet |
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map((num) => num * 2);
console.log(doubledNumbers);(1)
1 | Output : [2, 4, 6, 8, 10] |
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers); (1)
1 | Output : [2, 4] |
const fruits = ["apple", "banana", "orange", "kiwi"];
const result = fruits.find((fruit) => fruit.includes("r"));
console.log(result);(1)
1 | Output : orange |
/* Utilisation de reduce pour calculer la somme des nombres */
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); (1)
/* Utilisation de reduce pour concaténer les éléments du tableau en une seule chaîne */
const words = ["Hello", " ", "World", "!"];
const concatenatedString = words.reduce((accumulator, currentValue) => accumulator + currentValue, "");
console.log(concatenatedString); (2)
1 | Output : 15 |
2 | Output : Hello World! |
const methode = () => {
return new Promise((resolve, reject) => {
if (Math.random() > 0.5) {
resolve("Tout va bien dans la méthode asynchrone 1");
} else {
reject(Error('Problème méthode 1'));
}
})
}
methode()
.then(reponse => console.log(reponse))(1)
.catch(alert => console.log(alert)) (2)
.then(() => console.log ("Tout est terminé"));(3)
1 | Quand la promesse est tenue, c’est ce code qui sera exécuté |
2 | Sinon, on rentre dans ce bloc de code |
3 | Ce code est toujours exécuté |
/**
* Détermine la couleur de l'adversaire en fonction de la couleur du joueur.
*
* @param {string} playerColor - La couleur du joueur (B ou W).
* @returns {string} La couleur de l'adversaire (B ou W).
* @example
* const playerColor = Crush.BLACK;
* const opponentColor = opponent(playerColor);
* console.log(opponentColor); // Renvoie Crush.WHITE
*/
const opponent = (playerColor) => {
let opponentColor = playerColor === Crush.BLACK ? Crush.WHITE : Crush.BLACK;
return opponentColor;
}