Maison > interface Web > js tutoriel > Maîtriser le mot-clé &#this&# en JavaScript : ne plus jamais regarder en arrière

Maîtriser le mot-clé &#this&# en JavaScript : ne plus jamais regarder en arrière

Susan Sarandon
Libérer: 2025-01-06 06:59:40
original
992 Les gens l'ont consulté

Mastering the

Le mot-clé this de JavaScript est un concept fondamental qui laisse souvent perplexe les développeurs débutants et chevronnés. Sa nature dynamique peut conduire à des comportements inattendus si elle n’est pas bien comprise. Ce guide complet vise à démystifier cela, en explorant ses différents contextes, nuances et meilleures pratiques, complété par des exemples illustratifs et des problèmes difficiles pour consolider votre compréhension.

Introduction à ceci

En JavaScript, this est un mot-clé qui fait référence à l'objet à partir duquel le code actuel est exécuté. Contrairement à certains autres langages de programmation où cela est lié statiquement, celui de JavaScript est déterminé dynamiquement en fonction de la façon dont une fonction est appelée.

1. Contexte mondial

Lorsqu'il n'est à l'intérieur d'aucune fonction, cela fait référence à l'objet global.

  • Dans les navigateurs : L'objet global est window.
  • Dans Node.js : L'objet global est global.

Exemple

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Remarque : En mode strict (« use strict » ;), ceci dans le contexte global reste l'objet global.

2. Contexte de la fonction

I. Fonctions régulières

Dans les fonctions régulières, cela est déterminé par la manière dont la fonction est appelée.

  • Liaison par défaut : Si une fonction est appelée sans aucun contexte, cela fait référence à l'objet global (ou non défini en mode strict).

Exemple :

function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or global (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  • Liaison implicite : Lorsqu'une fonction est appelée en tant que méthode d'un objet, cela fait référence à cet objet.

Exemple

const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm Alice"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous pouvons utiliser call, apply ou bind pour définir explicitement cela.

function greet() {
  console.log(`Hello, I'm ${this.name}`);
}

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

II. Fonctions des flèches

Les fonctions fléchées ont un lexical this, ce qui signifie qu'elles héritent de celui-ci de la portée environnante au moment de leur création.

Exemple

const person = {
  name: 'Charlie',
  greet: () => {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication : Puisque les fonctions fléchées n'ont pas leur propre this, cela fait référence à l'objet global, pas à l'objet personne.

Utilisation correcte avec les fonctions fléchées :

const person = {
  name: 'Dana',
  greet: function() {
    const inner = () => {
      console.log(`Hello, I'm ${this.name}`);
    };
    inner();
  }
};

person.greet(); // "Hello, I'm Dana"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Aspect difficile : Si une méthode est assignée à une variable et appelée, elle peut perdre son contexte prévu.
Exemple

const calculator = {
  value: 0,
  add: function(num) {
    this.value += num;
    return this.value;
  }
};

console.log(calculator.add(5)); // 5
console.log(calculator.add(10)); // 15

const addFunction = calculator.add;
console.log(addFunction(5)); // NaN (in non-strict mode, this.value is undefined + 5)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

3. Fonctions du constructeur et ceci

Lorsqu'une fonction est utilisée comme constructeur avec le mot-clé new, cela fait référence à l'instance nouvellement créée.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Remarques importantes :
• Si new n'est pas utilisé, cela peut faire référence à l'objet global ou être indéfini en mode strict.
• Les constructeurs mettent généralement la première lettre en majuscule pour les distinguer des fonctions normales.

4. Le ceci dans les gestionnaires d'événements

Dans les gestionnaires d'événements, cela fait référence à l'élément qui a reçu l'événement.

Exemple

function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or global (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

5. Liaison explicite avec appel, application et liaison

JavaScript fournit des méthodes pour définir explicitement la valeur de this :

  • call : Invoque la fonction avec cet ensemble avec le premier argument, suivi des arguments de la fonction.
const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm Alice"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  • apply : Similaire à call, mais accepte les arguments sous forme de tableau.
function greet() {
  console.log(`Hello, I'm ${this.name}`);
}

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  • bind : Renvoie une nouvelle fonction avec ceci lié au premier argument.
const person = {
  name: 'Charlie',
  greet: () => {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cas d'utilisation :

  • Méthodes d'emprunt à d'autres objets.
  • Assurer que cela reste cohérent dans les rappels.

6. ceci en cours

ES6 a introduit des classes, qui fournissent une syntaxe plus claire pour les fonctions et méthodes du constructeur. Dans les méthodes de classe, cela fait référence à l'instance.
Exemple :

const person = {
  name: 'Dana',
  greet: function() {
    const inner = () => {
      console.log(`Hello, I'm ${this.name}`);
    };
    inner();
  }
};

person.greet(); // "Hello, I'm Dana"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Fonctions des flèches dans les classes :
Les fonctions fléchées peuvent être utilisées pour que les méthodes héritent de cela du contexte de classe, utile pour les rappels.

const calculator = {
  value: 0,
  add: function(num) {
    this.value += num;
    return this.value;
  }
};

console.log(calculator.add(5)); // 5
console.log(calculator.add(10)); // 15

const addFunction = calculator.add;
console.log(addFunction(5)); // NaN (in non-strict mode, this.value is undefined + 5)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pièges courants et meilleures pratiques

I. Perdre ce contexte

Lors du passage de méthodes en tant que rappels, le contexte d'origine peut être perdu.
Problème

function Person(name) {
  this.name = name;
}

const alice = new Person('Alice');
console.log(alice.name); // "Alice"
Copier après la connexion
Copier après la connexion

Solution
Utilisez bind pour préserver le contexte.

<button>



<p><strong>Arrow Function Caveat:</strong><br>
Using arrow functions in event handlers can lead to this referring to the surrounding scope instead of the event target.<br>
<strong>Example:</strong><br>
</p>

<pre class="brush:php;toolbar:false">button.addEventListener('click', () => {
  console.log(this); // Global object or enclosing scope
});
Copier après la connexion
Copier après la connexion

II. Utilisation incorrecte des fonctions fléchées

Les fonctions fléchées n'ont pas leur propre this, ce qui peut entraîner un comportement inattendu lorsqu'elles sont utilisées comme méthodes.

Problème

function greet(greeting) {
  console.log(`${greeting}, I'm ${this.name}`);
}

const person = { name: 'Eve' };
greet.call(person, 'Hello'); // "Hello, I'm Eve"
Copier après la connexion
Copier après la connexion

Solution
Utilisez des fonctions régulières pour les méthodes objet.

greet.apply(person, ['Hi']); // "Hi, I'm Eve"
Copier après la connexion
Copier après la connexion

III. Éviter Global ceci

La définition involontaire de propriétés sur l'objet global peut entraîner des bugs.

Problème

const boundGreet = greet.bind(person);
boundGreet('Hey'); // "Hey, I'm Eve"
Copier après la connexion
Copier après la connexion

Solution
Utilisez le mode strict ou une liaison appropriée.

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

const dog = new Animal('Dog');
dog.speak(); // "Dog makes a noise."
Copier après la connexion
Copier après la connexion

Concepts avancés

I. ceci dans les fonctions imbriquées

Dans les fonctions imbriquées, this ne peut pas faire référence au this externe. Les solutions incluent l'utilisation de fonctions fléchées ou leur stockage dans une variable.
Exemple avec la fonction flèche :

class Person {
  constructor(name) {
    this.name = name;
  }

  greet = () => {
    console.log(`Hello, I'm ${this.name}`);
  }
}

const john = new Person('John');
john.greet(); // "Hello, I'm John"
Copier après la connexion
Copier après la connexion

Exemple avec variable :

const obj = {
  name: 'Object',
  getName: function() {
    return this.name;
  }
};

const getName = obj.getName;
console.log(getName()); // undefined or global name
Copier après la connexion
Copier après la connexion

II. ceci avec des prototypes

Lors de l'utilisation de prototypes, cela fait référence à l'instance.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Conclusion

Le mot-clé this en JavaScript est une fonctionnalité polyvalente et puissante qui, lorsqu'elle est correctement comprise, peut considérablement améliorer vos capacités de codage.


10 problèmes délicats pour maîtriser cela

Pour vraiment consolider votre compréhension de cela, abordez les problèmes difficiles suivants. Chaque problème est conçu pour tester différents aspects et cas extrêmes du mot-clé this en JavaScript. Des solutions à la fin.

Problème 1 : la sortie mystérieuse

function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or global (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 2 : surprise de la fonction flèche

const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm Alice"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 3 : lier ceci dans un rappel

function greet() {
  console.log(`Hello, I'm ${this.name}`);
}

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 4 : utiliser correctement bind

const person = {
  name: 'Charlie',
  greet: () => {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 5 : ceci dans les fonctions du constructeur

const person = {
  name: 'Dana',
  greet: function() {
    const inner = () => {
      console.log(`Hello, I'm ${this.name}`);
    };
    inner();
  }
};

person.greet(); // "Hello, I'm Dana"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 6 : contexte du gestionnaire d'événements

const calculator = {
  value: 0,
  add: function(num) {
    this.value += num;
    return this.value;
  }
};

console.log(calculator.add(5)); // 5
console.log(calculator.add(10)); // 15

const addFunction = calculator.add;
console.log(addFunction(5)); // NaN (in non-strict mode, this.value is undefined + 5)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème 8 : ceci dans les promesses

function Person(name) {
  this.name = name;
}

const alice = new Person('Alice');
console.log(alice.name); // "Alice"
Copier après la connexion
Copier après la connexion

Problème 9 : Chaînage avec liaison

<button>



<p><strong>Arrow Function Caveat:</strong><br>
Using arrow functions in event handlers can lead to this referring to the surrounding scope instead of the event target.<br>
<strong>Example:</strong><br>
</p>

<pre class="brush:php;toolbar:false">button.addEventListener('click', () => {
  console.log(this); // Global object or enclosing scope
});
Copier après la connexion
Copier après la connexion

Problème 10 : ceci avec les classes et l'héritage

function greet(greeting) {
  console.log(`${greeting}, I'm ${this.name}`);
}

const person = { name: 'Eve' };
greet.call(person, 'Hello'); // "Hello, I'm Eve"
Copier après la connexion
Copier après la connexion

Solutions à des problèmes délicats

Solution au problème 1 :

Lorsque getName est attribué à une variable et appelé sans aucun contexte d'objet, la valeur par défaut est l'objet global. En mode non strict, this.name fait référence au nom global, qui est « Global ». En mode strict, cela ne serait pas défini, ce qui entraînerait une erreur.

greet.apply(person, ['Hi']); // "Hi, I'm Eve"
Copier après la connexion
Copier après la connexion

Solution au problème 2 :

Les fonctions fléchées n'ont pas leur propre ceci ; ils en héritent du périmètre environnant. Dans ce cas, la portée environnante est le contexte global, où this.name est « Global ».

const boundGreet = greet.bind(person);
boundGreet('Hey'); // "Hey, I'm Eve"
Copier après la connexion
Copier après la connexion

Solution au problème 3 :

Dans le rappel setInterval, this fait référence à l'objet global (ou n'est pas défini en mode strict). Ainsi, this.seconds incrémente window.seconds ou génère une erreur en mode strict. Le timer.seconds reste 0.

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

const dog = new Animal('Dog');
dog.speak(); // "Dog makes a noise."
Copier après la connexion
Copier après la connexion

Solution au problème 4 :

Après avoir lié retrieveX au module, l'appel deboundGetX() le définit correctement sur module.

class Person {
  constructor(name) {
    this.name = name;
  }

  greet = () => {
    console.log(`Hello, I'm ${this.name}`);
  }
}

const john = new Person('John');
john.greet(); // "Hello, I'm John"
Copier après la connexion
Copier après la connexion

Solution au problème 5 :

La fonction fléchée getModel hérite de cela du constructeur, qui fait référence à l'instance de voiture nouvellement créée.

const obj = {
  name: 'Object',
  getName: function() {
    return this.name;
  }
};

const getName = obj.getName;
console.log(getName()); // undefined or global name
Copier après la connexion
Copier après la connexion

Solution au problème 6 :

Dans les gestionnaires d'événements utilisant des fonctions régulières, cela fait référence à l'élément DOM qui a reçu l'événement, qui est le bouton. Étant donné que le bouton n'a pas de propriété name, this.name n'est pas défini.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Solution au problème 7 :

  • Premier console.log(this.name); inside outsideFunc fait référence à obj, donc il imprime « Outer ».
  • Deuxième console.log(this.name); à l'intérieur de innerFunc fait référence à l'objet global, il imprime donc « Global » ou non défini en mode strict.
function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or global (in Node.js)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Solution au problème 8 :

Dans le constructeur Promise, this fait référence à l'objet global (ou n'est pas défini en mode strict). Ainsi, this.value n'est pas défini (ou provoque une erreur en mode strict).

const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm Alice"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Solution au problème 9 :

La fonction multiplier est liée au premier argument a comme 2. Lorsque double(5) est appelé, elle calcule effectivement multiplier(2, 5).

function greet() {
  console.log(`Hello, I'm ${this.name}`);
}

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Solution au problème 10 :

Dans la méthode speak de la classe Dog, le rappel setTimeout est une fonction régulière. Ainsi, ceci à l'intérieur du rappel fait référence à l'objet global, et non à l'instance du chien. this.name est « non défini » ou provoque une erreur si le nom n’est pas défini globalement.

const person = {
  name: 'Charlie',
  greet: () => {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pour résoudre ce problème, utilisez une fonction flèche :

const person = {
  name: 'Dana',
  greet: function() {
    const inner = () => {
      console.log(`Hello, I'm ${this.name}`);
    };
    inner();
  }
};

person.greet(); // "Hello, I'm Dana"
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Maintenant, il enregistre correctement :

const calculator = {
  value: 0,
  add: function(num) {
    this.value += num;
    return this.value;
  }
};

console.log(calculator.add(5)); // 5
console.log(calculator.add(10)); // 15

const addFunction = calculator.add;
console.log(addFunction(5)); // NaN (in non-strict mode, this.value is undefined + 5)
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal