Déclaration et initialisation

S'il est déclaré en const, ça protège le nom de la variable, mais pas son contenu.
let etudiant = {
  nom:'Joe',
  age:20,
  moyenne:14.57,
  "une prop":true
};

Propriétés

Une propriété peut contenir un string, un entier, un nombre à virgule flottante, un boolean, un tableau, un objet, une fonction (une fonction dans un objet s'appelle une méthode).

Accéder aux propriétés

On peut accéder aux valeurs des propriétés d'un objet de deux manières.
let etudiant = {
  nom:'Joe',
  age:20,
  moyenne:14.57,
  "une prop":true
};

etudiant[`une prop`] = 2
etudiant.age = 25

console.log(etudiant.nom, etudiant.age, etudiant[`une prop`])
console.log(`nom ${etudiant.nom} ${etudiant.age} ans ${etudiant['une prop']}`)

Ajouter une propriété

let etudiant = {
  nom:'Joe',
  age:20,
};

etudiant[`une prop`] = 2
etudiant.test = 25

console.log(etudiant[`une prop`], etudiant.test)
console.log(`nom ${etudiant['une prop']} ${etudiant.test} ans`)

Supprimer une propriété

var etudiant = {
	nom:"Joe",
	age:28
};

delete etudiant.age;

Méthodes

var etudiant = {
  nom:"Joe",
  dire: function(msg){
    alert(msg)
  },
  age:28
};

etudiant.dire('bonjour')
const etudiant = {
    age:25,
    nom:'Joe',
    open:function(i){
        console.log(this.nom, 'open',i);
    },
    // une méthode peut se noter plus simplement
    close(){
        console.log(this.nom, 'close');
    }
};

console.log(etudiant.nom);
etudiant.nom='Bill';
etudiant.open(25);
etudiant.close();

Ajouter une méthode à un objet

let etudiant = {
  nom:'Joe',
  age:20,
};

etudiant.getage = function() {
  return this.age;
};

etudiant.dire = function(msg) {
  alert(msg);
};

console.log(etudiant.getage())
etudiant.dire('bonjour')
Le mot clé this fait référence à l'objet qui l'emploie.

Tableau d'objets

Déclaration initialisation

const etudiants = [
    {nom:'Joe', age:25},
    {nom:'Bill', age:32, enretard: true},
];

for

for(let n=0; n<etudiants.length; n++){
	console.log(etudiants[n].nom)
	if(etudiants[n].enretard) alert(`${etudiants[n].nom} est en retard`)
}

for in

for(n in etudiants){
	console.log(etudiants[n].nom)
}

for(n in etudiants){
	// très pratique: stocker la référence dans une variable temporaire
	const x = etudiants[n]
	console.log(x.nom)
}

while

let n=0
while(n < etudiants.length){
	console.log(etudiants[n].nom)
	n++
}

do while

let n=0
do{
	console.log(etudiants[n].nom)
	n++
} while(n < etudiants.length)

forEach

etudiants.forEach((x,id) => {console.log(id+' '+x.nom+'/'+x.age);});

for...of

parcourt directement les éléments
for (const etudiant of etudiants) {
    console.log(etudiant);
}

for (const [n, personne] of etudiants.entries()) {
    // n = indice, personne = objet
    console.log(`index:${n}, ${personne.nom} ${personne.age}`);
}

Objet JSON

Création d'une table HTML à partir d'un objet JSON
var livres = {
 "Pascal": [
    {"nom": "Pascal facile", "prix": 70},
    {"nom": "Guide Pascal", "prix": 40}
 ],

 "PHP": [
    {"nom": "PHP rapide", "prix": 10},
    {"nom": "PHP en profondeur", "prix": 13.5}
 ]
}

let s =`
	<table border="1" style="border-collapse:collapse">
	<caption>Livres</caption>
	<tr><th>Nom</th><th>Prix</th></tr>`

for(let n=0; n<livres.Pascal.length; n++){
	s += `
	<tr>
		<td>${livres.Pascal[n].nom}</td>
		<td>${livres.Pascal[n].prix}</td>
	</tr>`
}

for(let n=0; n<livres.PHP.length; n++){
	s += `
	<tr>
		<td>${livres.PHP[n].nom}</td>
		<td>${livres.PHP[n].prix}</td>
	</ttr>`
}

document.body.innerHTML = s+'</table>'
Livres
NomPrix
Pascal facile 70
Guide Pascal 40
PHP rapide 10
PHP en profondeur 13.5


Copier un objet

Le comportement de la copie d'un objet est différent d'une variable classique.
// Pour une variable et non un objet
let a = 2
// Crée une nouvelle variable et lui affecte la valeur de a
let b = a
b = 4
console.log(a) // 2
console.log(b) // 4
// b et a sont deux variables distinctes.


// Pour un objet
const a = { mission: 'Défendre' };
const b = a;
b.mission = 'Attaquer';
console.log(a.mission); // 'Attaquer'

//a et b désignent le même objet. Tu n'as pas créé de copie.
//b = a copie la référence à l'objet, pas l'objet lui-même.
// C'est une copie superficielle (Shallow copy).



// Pour une copie profonde de l'objet (un clonage), il faut structuredClone()
const a = { mission: 'Défendre' };
const b = structuredClone(a);
b.mission = 'Attaquer';
console.log(a.mission); // 'Défendre'

Copie superficielle d'un tableau d'objets

// Copier le tableau, mais pas les objets qu'il contient

const phase1 = [
    { mission: 'Défendre' },
    { mission: 'Surveiller' }
];

const phase2 = [...phase1]; // copie superficielle (shallow copy)
phase2[0].mission = 'Attaquer';
console.log(phase1[0].mission); // 'Attaquer' !

// L'opérateur ... crée un nouveau tableau,
// mais les objets à l'intérieur sont toujours partagés.
Cette subtilité piège même des développeurs expérimentés.

Copie profonde (Deep copy)

// Pour une copie profonde de l'objet (un clonage), il faut structuredClone()
const a = { mission: 'Défendre' };
const b = structuredClone(a);
b.mission = 'Attaquer';
console.log(a.mission); // 'Défendre'

Le passage de tableau d'objets en argument de fonction

const t = [
	{nom:'Joe',age: 25},
	{nom:'Bill',age: 32}
]

function test(tableau){
	tableau.push({champ:'ok', test:23})
}

test(t);
console.log(t) // Le tableau contient maintenant les trois objets
Javascript passe les tableaux par référence, contrairement au C et PHP pour lesquels il faut explicitement passer en référence, sinon c'est une copie locale à la fonction qui est créée, et supprimée en fin de fonction, sans altérer le tableau externe à la fonction.

En d'autres termes, JavaScript passe toujours ses arguments par valeur.
Pour un objet, cette valeur est une référence vers l'objet.
C'est pour ça qu'une fonction peut modifier son contenu, mais que réaffecter son paramètre ne remplace pas la variable d'origine.