ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript の this キーワードをマスターする: もう振り返る必要はありません
JavaScript の this キーワードは、初心者と熟練の開発者の両方を同様に困惑させることが多い基本的な概念です。その動的な性質を十分に理解していないと、予期しない動作が発生する可能性があります。この包括的なガイドは、さまざまな背景、ニュアンス、ベスト プラクティスを探求し、これをわかりやすくすることを目的としています。また、理解を確実にするための具体的な例や難しい問題も完備しています。
JavaScript では、this は、現在のコードが実行されているオブジェクトを参照するキーワードです。 this が静的にバインドされる他のプログラミング言語とは異なり、JavaScript の this は関数の呼び出し方法に基づいて動的に決定されます。
関数内にない場合、これはグローバル オブジェクトを参照します。
例
console.log(this === window); // true (in browser) console.log(this === global); // true (in Node.js)
注: strict モード ('use strict';) では、グローバル コンテキスト内の this はグローバル オブジェクトのままです。
通常の関数では、これは関数の呼び出し方法によって決まります。
例:
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"
これを明示的に設定するには、call、apply、または bind を使用できます。
function greet() { console.log(`Hello, I'm ${this.name}`); } const person = { name: 'Bob' }; greet.call(person); // "Hello, I'm Bob"
アロー関数には語彙的な this があり、作成時に周囲のスコープから this を継承します。
例
const person = { name: 'Charlie', greet: () => { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm undefined" (or global name if defined)
説明: アロー関数には独自の this がないため、this は person オブジェクトではなく、グローバル オブジェクトを参照します。
アロー関数の正しい使用法:
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)
関数が new キーワードを使用してコンストラクターとして使用される場合、これは新しく作成されたインスタンスを参照します。
console.log(this === window); // true (in browser) console.log(this === global); // true (in Node.js)
重要な注意事項:
• new が使用されない場合、これはグローバル オブジェクトを参照するか、厳密モードで未定義になる可能性があります。
• コンストラクターは通常、通常の関数と区別するために最初の文字を大文字にします。
イベント ハンドラーでは、これはイベントを受信した要素を指します。
例
function showThis() { console.log(this); } showThis(); // Window object (in browser) or global (in Node.js)
JavaScript には、この値を明示的に設定するメソッドが用意されています。
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)
使用例:
ES6 では、コンストラクター関数とメソッドのより明確な構文を提供するクラスが導入されました。クラスメソッド内では、これはインスタンスを指します。
例:
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 });
アロー関数には独自の this がないため、メソッドとして使用すると予期しない動作が発生する可能性があります。
問題
function greet(greeting) { console.log(`${greeting}, I'm ${this.name}`); } const person = { name: 'Eve' }; greet.call(person, 'Hello'); // "Hello, I'm Eve"
解決策
オブジェクトメソッドには通常の関数を使用してください。
greet.apply(person, ['Hi']); // "Hi, I'm Eve"
グローバル オブジェクトに意図せずプロパティを設定すると、バグが発生する可能性があります。
問題
const boundGreet = greet.bind(person); boundGreet('Hey'); // "Hey, I'm Eve"
解決策
厳密モードまたは適切なバインディングを使用してください。
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."
入れ子関数では、this は外側の this を参照しない場合があります。解決策には、アロー関数を使用するか、これを変数に保存することが含まれます。
アロー関数を使用した例:
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"
変数を使用した例:
const obj = { name: 'Object', getName: function() { return this.name; } }; const getName = obj.getName; console.log(getName()); // undefined or global name
プロトタイプを使用する場合、これはインスタンスを指します。
console.log(this === window); // true (in browser) console.log(this === global); // true (in Node.js)
JavaScript の this キーワードは、正しく理解すればコーディング能力を大幅に向上できる多用途で強力な機能です。
これについての理解を確実にするために、次の難しい問題に取り組んでください。各問題は、JavaScript の this キーワードのさまざまな側面とエッジ ケースをテストするように設計されています。最終的には解決策です。
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"
getName が変数に割り当てられ、オブジェクト コンテキストなしで呼び出される場合、これはデフォルトでグローバル オブジェクトになります。非厳密モードでは、this.name はグローバル名「Global」を参照します。厳密モードでは、これは未定義となり、エラーが発生します。
greet.apply(person, ['Hi']); // "Hi, I'm Eve"
アロー関数には独自の this がありません。周囲のスコープからそれを継承します。この場合、周囲のスコープはグローバル コンテキストであり、this.name は「Global」です。
const boundGreet = greet.bind(person); boundGreet('Hey'); // "Hey, I'm Eve"
setInterval コールバック内で、これはグローバル オブジェクトを参照します (または、厳密モードでは未定義です)。したがって、this.seconds は window.seconds をインクリメントするか、厳密モードでエラーをスローします。 timer.秒は 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."
retrieveX を module にバインドした後、boundGetX() を呼び出すと、これが 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"
アロー関数 getModel はコンストラクターからこれを継承し、新しく作成された車のインスタンスを参照します。
const obj = { name: 'Object', getName: function() { return this.name; } }; const getName = obj.getName; console.log(getName()); // undefined or global name
通常の関数を使用するイベント ハンドラーでは、イベントを受信した DOM 要素 (ボタン) を指します。ボタンには name プロパティがないため、this.name は未定義です。
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)
Promise コンストラクター内で、これはグローバル オブジェクトを参照します (または、厳密モードでは未定義です)。したがって、this.value は未定義です (または、厳密モードでエラーが発生します)。
const person = { name: 'Alice', greet: function() { console.log(`Hello, I'm ${this.name}`); } }; person.greet(); // "Hello, I'm Alice"
multiply 関数は、最初の引数 a を 2 としてバインドされています。double(5) が呼び出されると、事実上、multiply(2, 5) が計算されます。
function greet() { console.log(`Hello, I'm ${this.name}`); } const person = { name: 'Bob' }; greet.call(person); // "Hello, I'm Bob"
Dog クラスの speech メソッドでは、setTimeout コールバックが通常の関数です。したがって、コールバック内の this は、dog インスタンスではなく、グローバル オブジェクトを参照します。 this.name は「未定義」であるか、名前がグローバルに定義されていない場合はエラーが発生します。
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)
以上がJavaScript の this キーワードをマスターする: もう振り返る必要はありませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。