JavaScript 類方法中的 this 指向問題

一個簡單的 JavaScript 類示例javascript

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  speak() {
    console.log(this)
  }
}

const p = new Person('Callback', 27)
p.speak();
複製代碼

執行上面的示例能夠看到控制檯輸出以下圖java

接下來作一個操做:markdown

const f = p.speak
f() // 輸出 undefined
複製代碼

這裏將常量 f 指向 speak() 方法,注意這裏是「指向」,並非「調用」。以後調用 f() 能夠觀察到控制檯輸出爲 undefined。那麼問題來了,爲何這麼賦值以後,函數內部的 this 再也不是 Person 的實例 p 而變成了 undefined函數

實際上,方法內部的 this 永遠指向的是調用這個方法的對象,經過 Person 的實例 p 調用 speak() 方法,那麼 this 就指向 p。後面將 speak 賦值給常量 f 後, f() 表示的就是經過全局的 window 對象來調用 f() 方法。按理說,f() 方法被調用時應該輸出 window 對象的信息,但這裏輸出的倒是 undefined。這是由於根據 JavaScript 的語法規則,全部在類中定義的方法都默認開啓局部嚴格模式。在嚴格模式下,全部指向 window 對象的 this,都所有變動爲 undefined。看下面的示例:ui

function demo() {
  console.log(this)
}
function demo2() {
 'use strict'
  console.log(this)
}
demo() // 輸出 window 對象信息
demo2() // 輸出 undefined
複製代碼

回到最初的問題,之因此調用 f() 方法後輸出 undefined,是由於 f 指向的方法 speak() 是在 Person 類中定義的,其默認開啓了局部嚴格模式。當 f() 被調用時,調用方爲 window 對象,這樣 this 就變成了 undefinedthis

其實這一點和 Java 中對方法的處理是相似的。每個實例對象都持有對方法的引用而不是保存一份方法,方法會自動在參數列表的最前面添加一個 this 參數,這就是咱們之因此可以在 Java 方法裏使用 this 關鍵字的緣由,而這個 this 指向的就是當前在調用這個方法的對象。區別在於,Java 裏全部的方法都不能脫離定義它的類,不能夠像 JavaScript 裏面把類的某個方法賦值給一個全局變量或常量。spa

相關文章
相關標籤/搜索