拾遺記4:this指向

JavaScript中 this的指向取決於function被誰調用,而不取決於其定義。

示例一

function fn() {
    console.log(this)
}
fn()

上例中,fn是被全局對象調用,因此this指向全局對象。node

示例二

const obj = {
    foo: function () {
        console.log(this)
    }
}
let fn = obj.foo
fn()
obj.foo()

上例中,fn方法指向obj.foo,因爲fn方法被全局對象調用,所以this指向全局對象。而直接調用obj.foo(),此時foo方法被obj調用,所以this指向obj。瀏覽器

示例三

function Foo() {
    console.log(this)
}
const f = new Foo()

上例中,Function Foo被看成構造函數進行了實力化,此時this指向實力化對象f。
ES2015中的class關鍵字是一種語法糖,其本質仍是聲明一個構造函數,所以其內部this指向可參考構造函數。app

示例四

function foo() {
    return () => {
        console.log(this)
    }
}
foo()()

箭頭函數雖然也是一種函數,可是其不改變內部this指向,也就是說在查找箭頭函數內部this指向時,查找的依然是包裹它的function的調用者。在上例中,foo函數返回的函數是被全局對象調用,所以this指向全局對象。函數

基於上面的四個例子,能夠總結出在JavaScript中查找this的步驟爲:this

  • 沿着做用域鏈由內向外查找查找最近的function(箭頭函數不是function),看這個function最終被誰調用。
  1. 被全局對象調用(做爲函數調用),如foo(), this指向全局對象。
  2. 被其餘對象調用(做爲方法調用),如foo.bar(),this指向最終調用這個方法的對象。
  3. 被看成構造函數調用,如new Person,this指向新生成的實力化對象。
  4. 特殊調用,如fn.call, fn.apply, fn.bind,此時this指向調用時傳入的參數。
  • 若是找不到function,this就指向全局對象。

this指向的全局對象是什麼?

在上面提到不少次this指向全局對象,那這個全局對象究竟是什麼?命令行

瀏覽器環境下

  • 非嚴格模式下,全局對象爲window。
  • 嚴格模式下,全局對象爲undefined。

node環境下

若是在命令行中經過node *.js 執行時,分爲下面兩種狀況。code

  • 若是this沒有在任何函數做用域中
if (true) {
    console.log(this)
}
console.log(this)
// true
console.log(this === module.exports)

在上例中,this指向{}。
由於nodejs爲保證文件的模塊做用域,在執行文件代碼時,會爲全部的文件代碼添加一個包裹函數,上面的執行相似於:對象

// exports 指向module.exports
function wrapped(exports) {
    if (true) {
        console.log(this)
    }
    console.log(this)
}
wrapped()

所以this會指向{}。ip

  • 若是this處在函數做用域中,this指向調用者。
function fn() {
    console.log(this)
}
fn()

在上例中,fn是全局對象調用,而node環境中,全局對象是Global,所以this指向Global。作用域

相關文章
相關標籤/搜索