JavaScript中的this問題超詳細(xì)總結(jié)
一、this的指向問題
1、全局環(huán)境的this
在全局環(huán)境中(即不在任何函數(shù)內(nèi)部),this 指向全局對象:
- 在瀏覽器環(huán)境中,this 指向 window 對象。
console.log(this); // 瀏覽器環(huán)境中輸出 window
- 在 Node.js 環(huán)境中,this 指向 global 對象(但在嚴(yán)格模式下,this 是 undefined)。
"use strict"; console.log(this); // 輸出 undefined
2、對象方法中的this
當(dāng) this 出現(xiàn)在對象的方法中時,this 指向調(diào)用該方法的對象。
const obj = { name: 'Alice', sayName: function () { console.log(this.name); } }; obj.sayName(); // 輸出 'Alice'
3、構(gòu)造函數(shù)中的 this
在構(gòu)造函數(shù)中,this 指向正在創(chuàng)建的實例對象。
function Person(name) { this.name = name; } const person1 = new Person('Bob'); console.log(person1.name); // 輸出 'Bob'
4、箭頭函數(shù)中的this
箭頭函數(shù)不會創(chuàng)建自己的 this,它會捕獲其所在上下文的 this 值。
const obj = { name: 'Alice', sayName: function () { const arrowFunc = () => { console.log(this.name); }; arrowFunc(); } }; obj.sayName(); // 輸出 'Alice' //箭頭函數(shù) arrowFunc 中的 this 繼承自 sayName 方法中的 this,即 obj
5、事件處理器中的 this
在 DOM 事件處理器中,this 默認(rèn)指向觸發(fā)事件的 DOM 元素
const button = document.querySelector('button'); button.addEventListener('click', function () { console.log(this); // 指向 button 元素 });
如果使用箭頭函數(shù)作為事件處理器,this 將不再指向 DOM 元素,而是繼承自外部作用域的 this
const button = document.querySelector('button'); button.addEventListener('click', () => { console.log(this); // 指向外部作用域的 this(可能是 window 或 undefined,取決于嚴(yán)格模式) });
6、 類中的 this
在類中,this 的行為與構(gòu)造函數(shù)類似,指向當(dāng)前實例對象。
class Person { constructor(name) { this.name = name; } sayName() { console.log(this.name); } } const person = new Person('Dave'); person.sayName(); // 輸出 'Dave'
二、回調(diào)函數(shù)中的this問題
this的指向在回調(diào)函數(shù)中會變得復(fù)雜,而this的指向問題也主要集中于回調(diào)函數(shù),因為回調(diào)函數(shù)的this與上下文的調(diào)用有關(guān),因此另開一個章節(jié)重新進(jìn)行分析:
1、普通函數(shù)作為回調(diào)函數(shù)
當(dāng)普通函數(shù)被用作回調(diào)函數(shù)時,this的指向通常取決于調(diào)用該函數(shù)的對象,而不是定義它的對象。默認(rèn)情況下,this在非嚴(yán)格模式下指向全局對象(瀏覽器中是 window),在嚴(yán)格模式下指向 undefined。
function myCallback() { console.log(this); } const obj = { method: function() { [1, 2, 3].forEach(myCallback); // myCallback 作為回調(diào)函數(shù) } }; obj.method(); // 輸出: // 在非嚴(yán)格模式下,輸出 window(瀏覽器環(huán)境) // 在嚴(yán)格模式下,輸出 undefined
2、對象方法作為回調(diào)函數(shù)
如果對象的方法被用作回調(diào)函數(shù),this 通常不會指向該對象,除非顯式綁定。
const obj = { name: 'Alice', sayName: function() { console.log(this.name); } }; [1, 2, 3].forEach(obj.sayName); // 輸出: // undefined(因為 this 不再指向 obj) // 或者報錯(如果 this.name 被訪問且 this 是 undefined 或 window)
3、 事件處理器中的回調(diào)函數(shù)
在 DOM 事件處理器中,this默認(rèn)指向觸發(fā)事件的 DOM 元素。如果使用箭頭函數(shù),this將繼承自外部作用域的 this。
const button = document.querySelector('button'); button.addEventListener('click', function() { console.log(this); // 指向 button 元素 }); button.addEventListener('click', () => { console.log(this); // 指向外部作用域的 this(可能是 window 或 undefined,取決于嚴(yán)格模式) });
4、async 回調(diào)函數(shù)中的 this
在 async 函數(shù)或 Promise 的回調(diào)中,this 的指向與普通函數(shù)相同,取決于調(diào)用方式。
const obj = { name: 'Alice', fetchData: async function() { const data = await new Promise((resolve) => { setTimeout(() => { resolve('Data fetched'); }, 1000); }); console.log(this.name); // 這里的 this 需要正確綁定 } }; // 使用箭頭函數(shù)或 bind 確保 this 指向 obj obj.fetchData().then(() => {}); // 正常輸出 'Alice' // 如果在另一個上下文中調(diào)用 fetchData,需要綁定 this const fetch = obj.fetchData; fetch.call(obj); // 或者使用 bind
三、改變this指向的方法
1、把關(guān)鍵字轉(zhuǎn)為變量
案例:
let xiaoming = { age: 18, introduce: function() { setTimeout(function() { console.log(this.age) }, 1000) } } xiaoming.introduce();
解決方案:
let xiaoming = { age: 18, introduce: function() { let a = this; //用一個變量a來儲存 setTimeout(function() { console.log(a.age) //此處變?yōu)檎{(diào)用a }, 1000) } } xiaoming.introduce();
2、綁定函數(shù)的this
案例:
class MyCom { constructor() { this.value = 100; } getValue() { return this.value; } } let mc = new MyCom(); console.log(mc.getValue()); // 結(jié)果: 100
如果修改為下面代碼:
class MyCom { constructor() { this.value = 100; } getValue() { return this.value; } } let btn = { value: 200 } let mc = new MyCom(); btn.getValue = mc.getValue; console.log(btn.getValue()); // 結(jié)果: 200。因為調(diào)用者變?yōu)榱薭tn
如果希望函數(shù)永遠(yuǎn)指向MyCom的實例對象:
class MyCom { constructor() { this.value = 100; this.getValue = this.getValue.bind(this); } getValue() { return this.value; //此時this被鎖定為MyCom的實例對象 } } let btn = { value: 200 } let mc = new MyCom(); btn.getValue = mc.getValue; console.log(btn.getValue()); // 結(jié)果: 100
bind方法的使用:每個函數(shù)本身都有一個bind方法,作用就是用來固定函數(shù)的this指向。其不會對函數(shù)本身進(jìn)行任何改造,實際上它會生成一個新的函數(shù)并返回(需要我們接收)如下:
function test() { } let newTest = test.bind(xiaoming); newTest(); // this永遠(yuǎn)指向xiaoming
3、箭頭函數(shù)(上文有提過)
4、使用call/apply代替bind
案例:
在上面中使用bind太過繁瑣,可以使用call/apply解決問題:
總結(jié)
到此這篇關(guān)于JavaScript中的this問題的文章就介紹到這了,更多相關(guān)js this問題總結(jié)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

詳解JavaScript中Hash Map映射結(jié)構(gòu)的實現(xiàn)

JS判斷來路是否是百度等搜索索引進(jìn)行彈窗或自動跳轉(zhuǎn)的實現(xiàn)代碼