Heim >Web-Frontend >js-Tutorial >Das Schlüsselwort „this' in JavaScript beherrschen: Nie wieder zurückblicken
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.
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.
Wenn es sich nicht innerhalb einer Funktion befindet, bezieht sich dies auf das globale Objekt.
Beispiel
console.log(this === window); // true (in browser) console.log(this === global); // true (in Node.js)
Hinweis:Im strikten Modus („use strict“;) bleibt dies im globalen Kontext das globale Objekt.
Bei regulären Funktionen wird dies dadurch bestimmt, wie die Funktion aufgerufen wird.
Beispiel:
function showThis() { console.log(this); } showThis(); // Window object (in browser) or global (in Node.js)
Beispiel
const person = { name: 'Alice', greet: function() { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm Alice"
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"
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)
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"
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)
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)
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.
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)
JavaScript bietet Methoden zum expliziten Festlegen des Werts von:
const person = { name: 'Alice', greet: function() { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm Alice"
function greet() { console.log(`Hello, I'm ${this.name}`); } const person = { name: 'Bob' }; greet.call(person); // "Hello, I'm Bob"
const person = { name: 'Charlie', greet: () => { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm undefined" (or global name if defined)
Anwendungsfälle:
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"
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)
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"
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 });
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"
Lösung
Verwenden Sie reguläre Funktionen für Objektmethoden.
greet.apply(person, ['Hi']); // "Hi, I'm Eve"
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"
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."
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"
Beispiel mit Variable:
const obj = { name: 'Object', getName: function() { return this.name; } }; const getName = obj.getName; console.log(getName()); // undefined or global name
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)
Das Schlüsselwort this in JavaScript ist eine vielseitige und leistungsstarke Funktion, die, wenn sie richtig verstanden wird, Ihre Programmierfähigkeiten erheblich verbessern kann.
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.
function showThis() { console.log(this); } showThis(); // Window object (in browser) or global (in Node.js)
const person = { name: 'Alice', greet: function() { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm Alice"
function greet() { console.log(`Hello, I'm ${this.name}`); } const person = { name: 'Bob' }; greet.call(person); // "Hello, I'm Bob"
const person = { name: 'Charlie', greet: () => { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm undefined" (or global name if defined)
const person = { name: 'Dana', greet: function() { const inner = () => { console.log(`Hello, I'm ${this.name}`); }; inner(); } }; person.greet(); // "Hello, I'm Dana"
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)
function Person(name) { this.name = name; } const alice = new Person('Alice'); console.log(alice.name); // "Alice"
<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 });
function greet(greeting) { console.log(`${greeting}, I'm ${this.name}`); } const person = { name: 'Eve' }; greet.call(person, 'Hello'); // "Hello, I'm Eve"
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"
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"
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 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"
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
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)
function showThis() { console.log(this); } showThis(); // Window object (in browser) or global (in Node.js)
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"
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"
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)
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"
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)
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!