1. JavaScript 中this 的指向

1.1 函數(shù)中this 的指向

JavaScript 中, 有3種類型的函數(shù): 箭頭函數(shù), 函數(shù)聲明式, 函數(shù)表達(dá)式; 它們的this 指向可以分類為:

  1. 箭頭函數(shù): 箭頭函數(shù)中的this 指向上一層環(huán)境作用域
  2. 函數(shù)聲明式/函數(shù)表達(dá)式: 函數(shù)聲明式/函數(shù)表達(dá)式中的this 指向函數(shù)的調(diào)用, 如果沒(méi)有顯式的函數(shù)調(diào)用, 那么則該函數(shù)運(yùn)行與全局作用域, 指向window/global

1.2 object 中this 的指向

JavaScript 中, 對(duì)于數(shù)據(jù)類型object, 其實(shí)也存著這this, Object 中的this 指向本身

const log = console.log.bind(console)

let obj = {
    objThis: function () {
        return this
    }
}

log(obj === obj.objThis()) // true

2. 箭頭函數(shù)中this 指向的情況

2.1 箭頭函數(shù)中this, 由上下文作用域決定

function Timer() {
    this.s1 = 0
    this.s2 = 0
    setInterval(() => {
        this.s1++ // 由于該匿名函數(shù)為箭頭函數(shù), 所以此時(shí)的this, 根據(jù)作用鏈域的規(guī)則將指向Timer
    }, 1000)
    setInterval(function () {
        // console.log(this)
        this.s2++ // 由于該匿名還是為函數(shù)表達(dá)式, 所以此時(shí)的this, 由于沒(méi)有顯式調(diào)用者, 將指向window
    }, 1000)
}

var timer = new Timer()

setTimeout(() => console.log('s1: ', timer.s1), 3100) // 3
setTimeout(() => console.log('s1: ', timer.s2), 3100) // 0

2.2 箭頭函數(shù)中的this 不會(huì)指向?qū)ο笾械膖his

箭頭函數(shù)中的this 指向的是沿著作用鏈域?qū)ふ疑舷挛淖饔糜? 但是這個(gè)作用域不包括對(duì)象中的this;
簡(jiǎn)而言之, 箭頭函數(shù)作為一個(gè)對(duì)象的方法時(shí), 此時(shí)箭頭函數(shù)中的this 將指向window/global, 不會(huì)指向?qū)ο蟊旧?/p>

const log = console.log.bind(console)

let obj = {
    objThis: function () {
        log(this)
    },
    say: () => {
        log(this)
    }
}

obj.objThis() // obj
obj.say() // window

3. 面試題

3.1 題目1

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()

解析:

var o = {
  f1: function () {
    console.log(this); // 該函數(shù)是函數(shù)表達(dá)式, 因此this 指向函數(shù)的調(diào)用, 即o 
    var f2 = function () {
      console.log(this); // 該函數(shù)是函數(shù)表達(dá)式, 且為立即調(diào)用函數(shù); 此時(shí)沒(méi)有顯式指定調(diào)用者, 則調(diào)用者為global/window
    }();
  }
}

o.f1()

3.2 面試2

當(dāng)箭頭函數(shù)作為一個(gè)對(duì)象的方法時(shí), 此時(shí)箭頭函數(shù)中的this 指向全局

let obj  = {
    f1: () => {
        console.log(this)
    }
}
obj.f1()