1. 程式人生 > 前端設計 >this到底是什麼?

this到底是什麼?

前言

this是JavaScript世界最讓人迷惑的關鍵字之一,如果不明白this的本質,基本上會被一線網際網路公司的面試官扣大量的分。上下文問有提到過this是上下文中確定的那麼我們來了解下什麼是this。

為什麼要有this?

function func() {
  console.log(aaa);
}
複製程式碼

如上述程式碼,函式func列印變數aaa,問題是這個函式func可以在任意其他執行上下文中被呼叫,因此這個a可能就指向不同了。

this就是指向當前程式碼執行時所處的上下文環境

this的一些理解

this 既不指向函式自身也不指向函式的作用域

  • this的指向,是在函式被呼叫的時候確定的,也就是執行上下文被建立時確定的。
  • this 的指向和函式宣告的位置沒有任何關係,只取決於函式的呼叫位置(也即由誰、在什麼地方呼叫這個函式) 。
  • 正因為在執行上下文的建立階段this的指向就已經被確定了,在執行階段this指向不可再被更改。

this指向規則

預設指向

預設this是指向全域性物件window的

function func() {
    console.log( this.b ); // this指向全域性物件
}
var b = 3;
func(); // 3
複製程式碼
  • 這是在預設正常執行環境下會執行window
  • 如果開啟了嚴格模式,那麼func()將會變為undefined,this執行undefiend
function func() {
  "use strict";//函式體處於嚴格模式下,this指向undefined
  console.log(this.age);
}

var age = "22";
(function() {
  func(); //age of undefined
})();
複製程式碼

setTimeout和setInterval指向?

可以發現在setInterval和setTimeout中傳入函式時,函式中的this會指向window物件

var num = 0;
class Obj {
    constructor(num){
        this.num = num;
    }
    func(){
        console
.log(this.num); } func1(){ setTimeout(function () { console.log("setTimeout:"+this.num); },1000) } func2(){ setInterval(function () { console.log(this.num); },2000) } } var obj = new Obj(1); obj.func();//>> 1  輸出的是obj.num obj.func1()//>> setTimeout:0  輸出的是window.num obj.func2()//>> 0 0 0 0 ……  輸出的是window.num 複製程式碼

可能是匿名函式做的鬼>v<,當然可以使用bind進行修正this指向即可解決

隱式this

通過執行時的上下文來決定,也就是呼叫的位置。

function func() {
    console.log(this.a);
  }
  var obj = {
    a: 2,func: func
  };
  obj.func(); // 2
複製程式碼
  • 找到呼叫位置,由 obj 物件來呼叫函式func,
  • 此時可以說函式func被呼叫時,obj 物件“擁有”或者“包含”func函式,
  • 所以此時的 this 指向呼叫 func 函式的 obj 物件。

隱式丟失?

function func() {
    console.log( this.a );
}

var obj = {
    a: "coffe1891",func: func
};

var bar = obj.func; // 間接引用,見本文【壹.2.3.6】。此時bar和obj.func其實
                    // 都指向記憶體中的函式func本身。
var a = "oops,global"; // a 是全域性物件window的屬性,也是全域性變數
bar(); //>> oops,global
複製程式碼
  • 可以理解為 bar 是 obj.func 的一個引用,但是實際上,它引用的是func函式本身
  • bar() 其實是一個不帶任何定語的獨立函式呼叫,所以就按預設指向,執行window

顯式this

JavaScript內建物件Function的三個原型方法call()、apply()和bind(),它們的第一個引數是一個物件,它們會把這個物件繫結到this,接著在呼叫函式時讓this指向這個物件。

var a = "makai";

function func() {
    console.log( this.a );
}
var obj = {
    a:"123123"
};

func.call(obj); // 123123
// 在呼叫 func 時強制把它的 this 繫結到 obj 上
複製程式碼

bind和call就不用我多說了把 bind不會立即執行,而apply會立即執行和call一樣,區別在於傳參不同

new中的this

通過 new的方式,this永遠指向新建立的物件

function func(name) {
    this.name = name;
    this.getName = function() {
      return this.name;
    };
  }
  
  var obj = new func("biubiubiu"); //this會指向obj
  obj.getName()//biubiubiu
複製程式碼

箭頭函式的this

箭頭函式的自身是沒有this的,箭頭函式的 this與宣告所在的上下文相同,預設為window,嚴格模式為undefined

var b = 11
var obj = {
    b: 22,a: () => {
        console.log(this.b);
    }
}
// 物件呼叫箭頭函式
obj.a(); // 11  thi=>window
複製程式碼

over 快樂每一天