Qu’est-ce que ‘this’ en JavaScript ?
‘this’ est un mot-clé qui référence un objet, mais quel objet dépend de comment la fonction est appelée.
Règle d’or : ‘this’ est déterminé à l’exécution (runtime), pas à la définition.
Exemple :
function greet() {
console.log(this.name);
}
const person = { name: 'Alice' };
greet(); // undefined (this = global)
greet.call(person); // 'Alice' (this = person)Quelles sont les 4 règles de binding pour ‘this’ (par ordre de priorité) ?
1. NEW binding (Priorité la plus haute)
- Appelée avec ‘new’, this = nouvel objet
2. Explicit binding
- call/apply/bind, this = objet passé
3. Implicit binding
- objet.méthode(), this = objet
4. Default binding (Priorité la plus basse)
- this = window/global (ou undefined en strict mode)
Ordre : new > explicit > implicit > default
Quel est le mnémonique pour ‘this’ ?
B.I.N.D
Que se passe-t-il dans ce code ?
const obj = {
name: 'Alice',
greet() { console.log(this.name); }
};
const greet = obj.greet;
greet();Résultat : ‘undefined’ (strict mode) ou ‘[nom de window.name]’ (non-strict)
Explication :
La méthode perd son contexte quand elle est assignée à une variable. ‘this’ devient l’objet global/undefined car il n’y a plus de binding implicite.
Solutions :
// 1. Arrow function const greet = () => obj.greet(); // 2. bind const greet = obj.greet.bind(obj); // 3. Appeler directement obj.greet();
Les arrow functions ont-elles leur propre ‘this’ ?
Non. Les arrow functions n’ont PAS leur propre ‘this’.
Elles héritent du ‘this’ de leur contexte lexical (où elles sont définies).
Conséquences :
- Elles ignorent call/apply/bind
- Elles ne peuvent pas être utilisées comme constructeurs
Exemple :
const obj = {
name: 'Alice',
regular: function() {
console.log(this.name); // 'Alice'
},
arrow: () => {
console.log(this.name); // undefined (this global)
}
};
obj.regular(); // 'Alice'
obj.arrow(); // undefinedComment fixer le problème de ‘this’ dans setTimeout ?
Problème :
const person = {
name: 'Alice',
greet() {
setTimeout(function() {
console.log(this.name); // undefined ❌
}, 1000);
}
};Solutions :
1. Arrow function (Recommandé) :
setTimeout(() => {
console.log(this.name); // 'Alice' ✓
}, 1000);2. bind :
setTimeout(function() {
console.log(this.name);
}.bind(this), 1000);3. Variable ‘that’ :
const that = this;
setTimeout(function() {
console.log(that.name); // 'Alice' ✓
}, 1000);Différence entre call, apply et bind ?
call(thisArg, arg1, arg2, …) :
- Invoque IMMÉDIATEMENT
- Arguments séparés par virgules
apply(thisArg, [args]) :
- Invoque IMMÉDIATEMENT
- Arguments en tableau
bind(thisArg, arg1, …) :
- N’invoque PAS
- Retourne une NOUVELLE fonction avec ‘this’ fixé
Mnémonique :
- Call : Comma-separated, Calls now
- Apply : Array, Also calls now
- Bind : Binds, But doesn’t call
Que vaut ‘this’ avec le new keyword ?
Avec ‘new’, JavaScript crée un nouveau objet et ‘this’ pointe vers cet objet.
Exemple :
function User(name) {
this.name = name;
}
const user = new User('Alice');
console.log(user.name); // 'Alice'Ce que fait ‘new’ en coulisses :
function User(name) {
// 1. const this = {};
// 2. this.\_\_proto\_\_ = User.prototype;
this.name = name;
// 3. return this;
}Que vaut ‘this’ dans une arrow function au niveau global ?
Le ‘this’ du contexte parent (généralement ‘window’ en navigateur, ou l’objet global en Node.js).
Exemple :
const greet = () => {
console.log(this);
};
greet(); // window (ou global en Node.js)Important :
const obj = {
value: 42,
getValue: () => this.value
};
obj.getValue(); // undefined
// L'arrow function hérite du this global, pas de obj !Fixez ce code :
const person = {
name: 'Bob',
friends: ['Alice', 'Charlie'],
showFriends() {
this.friends.forEach(function(friend) {
console.log(this.name + ' knows ' + friend);
});
}
};Solutions :
1. Arrow function (Recommandé) :
showFriends() {
this.friends.forEach(friend => {
console.log(this.name + ' knows ' + friend);
});
}2. bind :
showFriends() {
this.friends.forEach(function(friend) {
console.log(this.name + ' knows ' + friend);
}.bind(this));
}3. thisArg (forEach accepte un 2e paramètre) :
showFriends() {
this.friends.forEach(function(friend) {
console.log(this.name + ' knows ' + friend);
}, this); // ← thisArg
}Peut-on changer le ‘this’ d’une arrow function avec bind ?
Non. Le ‘this’ d’une arrow function est fixé à sa création (lexical binding) et ne peut PAS être changé.
Exemple :
const greet = () => {
console.log(this.name);
};
const person = { name: 'Alice' };
greet.call(person); // undefined (ignoré!)
greet.apply(person); // undefined (ignoré!)
const bound = greet.bind(person);
bound(); // undefined (ignoré!)Les arrow functions ignorent complètement call, apply et bind pour ‘this’.
Comment créer une calculatrice chaînée avec ‘this’ ?
const calculator = {
value: 0,
add(n) {
this.value += n;
return this; // Retourne l'objet pour chaînage
},
subtract(n) {
this.value -= n;
return this;
},
multiply(n) {
this.value *= n;
return this;
},
divide(n) {
this.value /= n;
return this;
},
result() {
return this.value;
}
};
const result = calculator
.add(5)
.multiply(3)
.add(2)
.result();
console.log(result); // 17