JS中的this指向什么?怎么控制?

this的指向取決于函數調用方式。1. 默認情況下,普通函數的this指向全局對象(如瀏覽器中為window),若作為對象方法調用則指向該對象,若通過new調用則指向新對象實例;2. 箭頭函數無自身this,繼承外層作用域的this;3. 可使用call、apply或bind手動綁定this,其中call和apply立即調用函數并分別以參數列表和數組傳參,bind返回一個綁定后的新函數;4. 常見問題出現在事件監聽或回調中,可通過bind或箭頭函數包裹來保持this指向預期對象。掌握這些規則可有效避免this帶來的混淆與錯誤。

JS中的this指向什么?怎么控制?

JavaScript中,this的指向是很多人剛開始學習時容易混淆的地方。它的值不是固定不變的,而是根據函數被調用的方式動態決定的。理解這一點,對寫出穩定、可維護的代碼非常重要。


1. this默認指向誰?

函數中的this指向取決于它被如何調用,而不是在哪里定義的。

  • 在普通函數中(非箭頭函數),this默認指向全局對象,在瀏覽器中就是window。
  • 如果函數是在某個對象的方法中被調用的,那么this就會指向那個對象。
  • 如果函數作為構造函數通過new調用,this會指向新創建的對象實例。

舉個例子:

const obj = {   name: 'Tom',   sayName: function() {     console.log(this.name);   } };  obj.sayName(); // 輸出 'Tom',this指向obj

但如果把方法單獨拿出來調用:

const func = obj.sayName; func(); // 輸出 undefined 或者 window.name(如果存在)

這時候this就不再指向obj了。


2. 箭頭函數的this怎么算?

箭頭函數沒有自己的this,它會捕獲外層作用域的this值。

也就是說,箭頭函數內部的this其實是它外層普通函數或全局作用域的this。

比如:

const obj = {   name: 'Jerry',   sayName: () => {     console.log(this.name); // 這里的 this 指向全局對象   } };  obj.sayName(); // 輸出 undefined 或 window.name

即使sayName是obj的一個屬性,由于它是箭頭函數,this仍然不會指向obj。

所以如果你希望this能綁定到當前對象,盡量不要使用箭頭函數作為對象的方法。


3. 如何手動控制this的指向?

JS提供了三種方法可以顯式指定函數執行時的this:

  • call
  • apply
  • bind

它們的區別在于傳參方式和調用時機:

  • call(obj, arg1, arg2):立即調用函數,參數依次傳遞。
  • apply(obj, [arg1, arg2]):立即調用,參數以數組形式傳入。
  • bind(obj, arg1, arg2):返回一個新函數,之后再調用。

例如:

function greet(greeting, punctuation) {   console.log(`${greeting}, ${this.name}${punctuation}`); }  const person = { name: 'Alice' };  greet.call(person, 'Hello', '!'); // Hello, Alice! greet.apply(person, ['Hi', '.']); // Hi, Alice. const sayHello = greet.bind(person, 'Hey'); sayHello('!!!'); // Hey, Alice!!!

這些方法常用于回調函數、事件處理等場景中,用來“鎖定”this的指向。


4. 常見的坑:事件監聽與回調中的this

dom事件監聽或異步操作中,this容易丟失預期的指向。

比如:

const button = document.querySelector('#btn'); button.addEventListener('click', obj.sayName); // 此時點擊按鈕輸出 undefined,因為 this 指向 button 元素

解決辦法通常是用bind提前綁定上下文,或者用閉包保存this:

button.addEventListener('click', obj.sayName.bind(obj));

或者用箭頭函數包裹:

button.addEventListener('click', () => obj.sayName());

不過要注意,這種方式其實是在調用函數,而不是綁定函數本身。


基本上就這些。
this看起來簡單,但稍不注意就容易出錯。關鍵在于記住一句話:函數怎么調用決定了this是誰。掌握不同調用方式下的規則,并學會用call/apply/bind來控制,就能避免很多問題。

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享