Heim > Web-Frontend > js-Tutorial > Das Schlüsselwort „this' in JavaScript beherrschen: Nie wieder zurückblicken

Das Schlüsselwort „this' in JavaScript beherrschen: Nie wieder zurückblicken

Susan Sarandon
Freigeben: 2025-01-06 06:59:40
Original
996 Leute haben es durchsucht

Mastering the

Das Schlüsselwort dies von JavaScript ist ein grundlegendes Konzept, das sowohl Anfängern als auch erfahrenen Entwicklern oft Rätsel aufgibt. Seine dynamische Natur kann zu unerwartetem Verhalten führen, wenn es nicht vollständig verstanden wird. Dieser umfassende Leitfaden soll dies entmystifizieren, indem er seine verschiedenen Kontexte, Nuancen und Best Practices untersucht, komplett mit anschaulichen Beispielen und herausfordernden Problemen, um Ihr Verständnis zu festigen.

Einführung dazu

In JavaScript ist this ein Schlüsselwort, das sich auf das Objekt bezieht, von dem aus der aktuelle Code ausgeführt wird. Im Gegensatz zu einigen anderen Programmiersprachen, bei denen dies statisch gebunden ist, wird dies bei JavaScript dynamisch bestimmt, basierend darauf, wie eine Funktion aufgerufen wird.

1. Globaler Kontext

Wenn es sich nicht innerhalb einer Funktion befindet, bezieht sich dies auf das globale Objekt.

  • In Browsern: Das globale Objekt ist Fenster.
  • In Node.js: Das globale Objekt ist global.

Beispiel

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Hinweis:Im strikten Modus („use strict“;) bleibt dies im globalen Kontext das globale Objekt.

2. Funktionskontext

I. Reguläre Funktionen

Bei regulären Funktionen wird dies dadurch bestimmt, wie die Funktion aufgerufen wird.

  • Standardbindung: Wenn eine Funktion ohne Kontext aufgerufen wird, bezieht sich dies auf das globale Objekt (oder auf undefiniert im strikten Modus).

Beispiel:

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

showThis(); // Window object (in browser) or global (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Implizite Bindung: Wenn eine Funktion als Methode eines Objekts aufgerufen wird, bezieht sich dies auf dieses Objekt.

Beispiel

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

person.greet(); // "Hello, I'm Alice"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir können call, apply oder bind verwenden, um dies explizit festzulegen.

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

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

II. Pfeilfunktionen

Pfeilfunktionen haben ein lexikalisches Dies, was bedeutet, dass sie dieses zum Zeitpunkt ihrer Erstellung vom umgebenden Bereich erben.

Beispiel

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

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Erklärung:Da Pfeilfunktionen kein eigenes This haben, bezieht sich dies auf das globale Objekt, nicht auf das Personenobjekt.

Korrekte Verwendung mit Pfeilfunktionen:

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

person.greet(); // "Hello, I'm Dana"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Herausfordernder Aspekt: Wenn eine Methode einer Variablen zugewiesen und aufgerufen wird, kann es sein, dass diese ihren beabsichtigten Kontext verliert.
Beispiel

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)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

3. Konstruktorfunktionen und das

Wenn eine Funktion als Konstruktor mit dem Schlüsselwort new verwendet wird, bezieht sich dies auf die neu erstellte Instanz.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wichtige Hinweise:
• Wenn new nicht verwendet wird, verweist dies möglicherweise auf das globale Objekt oder ist im strikten Modus undefiniert.
• Konstruktoren schreiben den ersten Buchstaben normalerweise groß, um sie von regulären Funktionen zu unterscheiden.

4. Das in Event-Handlern

In Event-Handlern bezieht sich dies auf das Element, das das Ereignis empfangen hat.

Beispiel

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

showThis(); // Window object (in browser) or global (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

5. Explizite Bindung mit Aufruf, Anwenden und Binden

JavaScript bietet Methoden zum expliziten Festlegen des Werts von:

  • Aufruf: Ruft die Funktion auf, wobei dieser Wert auf das erste Argument gesetzt ist, gefolgt von Funktionsargumenten.
const person = {
  name: 'Alice',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm Alice"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • apply: Ähnlich wie call, akzeptiert aber Argumente als Array.
function greet() {
  console.log(`Hello, I'm ${this.name}`);
}

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • bind: Gibt eine neue Funktion zurück, die an das erste Argument gebunden ist.
const person = {
  name: 'Charlie',
  greet: () => {
    console.log(`Hello, I'm ${this.name}`);
  }
};

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Anwendungsfälle:

  • Ausleihen von Methoden von anderen Objekten.
  • Sicherstellen, dass dies bei Rückrufen konsistent bleibt.

6. Dies im Unterricht

ES6 führte Klassen ein, die eine klarere Syntax für Konstruktorfunktionen und -methoden bieten. Innerhalb von Klassenmethoden bezieht sich dies auf die Instanz.
Beispiel:

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

person.greet(); // "Hello, I'm Dana"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Pfeilfunktionen in Klassen:
Pfeilfunktionen können für Methoden verwendet werden, um dies vom Klassenkontext zu erben, was für Rückrufe nützlich ist.

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)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Häufige Fallstricke und Best Practices

I. Den Kontext verlieren

Beim Übergeben von Methoden als Rückrufe kann der ursprüngliche Kontext verloren gehen.
Problem

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

const alice = new Person('Alice');
console.log(alice.name); // "Alice"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung
Verwenden Sie Bind, um den Kontext beizubehalten.

<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
});
Nach dem Login kopieren
Nach dem Login kopieren

II. Pfeilfunktionen falsch verwenden

Pfeilfunktionen haben kein eigenes This, was bei Verwendung als Methoden zu unerwartetem Verhalten führen kann.

Problem

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

const person = { name: 'Eve' };
greet.call(person, 'Hello'); // "Hello, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung
Verwenden Sie reguläre Funktionen für Objektmethoden.

greet.apply(person, ['Hi']); // "Hi, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

III. Globales vermeiden

Das unbeabsichtigte Festlegen von Eigenschaften für das globale Objekt kann zu Fehlern führen.

Problem

const boundGreet = greet.bind(person);
boundGreet('Hey'); // "Hey, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung
Verwenden Sie den strikten Modus oder die richtige Bindung.

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."
Nach dem Login kopieren
Nach dem Login kopieren

Fortgeschrittene Konzepte

I. dies in verschachtelten Funktionen

In verschachtelten Funktionen bezieht sich this möglicherweise nicht auf das äußere This. Zu den Lösungen gehören die Verwendung von Pfeilfunktionen oder das Speichern dieser in einer Variablen.
Beispiel mit Pfeilfunktion:

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"
Nach dem Login kopieren
Nach dem Login kopieren

Beispiel mit Variable:

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

const getName = obj.getName;
console.log(getName()); // undefined or global name
Nach dem Login kopieren
Nach dem Login kopieren

II. dies mit Prototypen

Bei der Verwendung von Prototypen bezieht sich dies auf die Instanz.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Abschluss

Das Schlüsselwort this in JavaScript ist eine vielseitige und leistungsstarke Funktion, die, wenn sie richtig verstanden wird, Ihre Programmierfähigkeiten erheblich verbessern kann.


10 knifflige Probleme, um dies zu meistern

Um Ihr Verständnis davon wirklich zu festigen, gehen Sie die folgenden herausfordernden Probleme an. Jedes Problem dient dazu, verschiedene Aspekte und Randfälle des Schlüsselworts this in JavaScript zu testen. Lösungen am Ende.

Problem 1: Die mysteriöse Ausgabe

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

showThis(); // Window object (in browser) or global (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 2: Überraschung mit der Pfeilfunktion

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

person.greet(); // "Hello, I'm Alice"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 3: Binden Sie dies in einen Rückruf

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

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 4: Bind richtig verwenden

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

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 5: Dies in Konstruktorfunktionen

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

person.greet(); // "Hello, I'm Dana"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 6: Event-Handler-Kontext

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)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Problem 8: Dies in Promises

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

const alice = new Person('Alice');
console.log(alice.name); // "Alice"
Nach dem Login kopieren
Nach dem Login kopieren

Problem 9: Verkettung mit bind

<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
});
Nach dem Login kopieren
Nach dem Login kopieren

Problem 10: Dies mit Klassen und Vererbung

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

const person = { name: 'Eve' };
greet.call(person, 'Hello'); // "Hello, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

Lösungen für knifflige Probleme

Lösung für Problem 1:

Wenn getName einer Variablen zugewiesen und ohne Objektkontext aufgerufen wird, wird standardmäßig das globale Objekt verwendet. Im nicht-strikten Modus bezieht sich this.name auf den globalen Namen, der „Global“ lautet. Im strikten Modus wäre dies undefiniert und würde zu einem Fehler führen.

greet.apply(person, ['Hi']); // "Hi, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 2:

Pfeilfunktionen haben kein eigenes This; Sie erben es vom umgebenden Bereich. In diesem Fall ist der umgebende Bereich der globale Kontext, wobei this.name „Global“ ist.

const boundGreet = greet.bind(person);
boundGreet('Hey'); // "Hey, I'm Eve"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 3:

Im setInterval-Rückruf bezieht sich dies auf das globale Objekt (oder ist im strikten Modus undefiniert). Somit erhöht this.seconds entweder window.seconds oder löst im strikten Modus einen Fehler aus. Die timer.seconds bleiben 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."
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 4:

Nach der Bindung von „retrieX“ an das Modul wird dies durch den Aufruf von „boundGetX()“ korrekt auf „Modul“ gesetzt.

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"
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 5:

Die Pfeilfunktion getModel erbt dies vom Konstruktor, der auf die neu erstellte Autoinstanz verweist.

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

const getName = obj.getName;
console.log(getName()); // undefined or global name
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 6:

In Event-Handlern, die reguläre Funktionen verwenden, bezieht sich dies auf das DOM-Element, das das Ereignis empfangen hat, also die Schaltfläche. Da die Schaltfläche keine Namenseigenschaft hat, ist this.name undefiniert.

console.log(this === window); // true (in browser)
console.log(this === global); // true (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 7:

  • Erstes console.log(this.name); inside äußereFunc bezieht sich auf obj und gibt daher „Outer“ aus.
  • Zweites console.log(this.name); inside innerFunc verweist auf das globale Objekt und gibt daher im strikten Modus „Global“ oder „undefiniert“ aus.
function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or global (in Node.js)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 8:

Im Promise-Konstruktor bezieht sich dies auf das globale Objekt (oder ist im strikten Modus undefiniert). Daher ist this.value undefiniert (oder verursacht einen Fehler im strikten Modus).

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

person.greet(); // "Hello, I'm Alice"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 9:

Die Multiplikationsfunktion ist an das erste Argument a als 2 gebunden. Wenn double(5) aufgerufen wird, berechnet es effektiv Multiplikation(2, 5).

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

const person = { name: 'Bob' };
greet.call(person); // "Hello, I'm Bob"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Lösung für Problem 10:

In der Speak-Methode der Dog-Klasse ist der setTimeout-Rückruf eine reguläre Funktion. Daher bezieht sich dies innerhalb des Rückrufs auf das globale Objekt, nicht auf die Hundeinstanz. this.name ist „undefiniert“ oder verursacht einen Fehler, wenn der Name nicht global definiert ist.

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

person.greet(); // "Hello, I'm undefined" (or global name if defined)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Um dieses Problem zu beheben, verwenden Sie eine Pfeilfunktion:

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

person.greet(); // "Hello, I'm Dana"
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Jetzt wird Folgendes korrekt protokolliert:

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)
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonDas Schlüsselwort „this' in JavaScript beherrschen: Nie wieder zurückblicken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage