前端學習筆記(5) - JavaScript中this 關鍵字的機制

JavaScript中有幾種函數

1.使用function定義的函數

function foo(){
}

2.使用箭頭函數定義的函數

const foo=()=>{
}

3.在class中定義的函數

class A{
  foo(){
  }
}

4.生成器函數

function* foo(){

}

5.class定義的類,實際上也是函數

class Foo {
    constructor(){
    }
}

6、7、8異步函數

async function foo(){
}
const foo = async () => {
}
async function foo*(){
}

不同函數this關鍵字的行爲


function showThis(){
    console.log(this);
}

var o = {
    showThis: showThis
}

showThis(); // global
o.showThis(); // o

普通函數的 this 值由“調用它所使用的引用”決定,其中奧祕就在於:我們獲取函數的表達式,它實際上返回的並非函數本身,而是一個 Reference 類型。Reference 類型由兩部分組成:一個對象和一個屬性值。

不難理解 o.showThis 產生的 Reference 類型,即由對象 o 和屬性“showThis”構成。

當做一些算術運算(或者其他運算時),Reference 類型會被解引用,即獲取真正的值(被引用的內容)來參與運算,而類似函數調用、delete 等操作,都需要用到 Reference 類型中的對象。在這個例子中,Reference 類型中的對象被當作 this 值,傳入了執行函數時的上下文當中。

調用函數時使用的引用,決定了函數執行時刻的 this 值。

const showThis = () => {
    console.log(this);
}

var o = {
    showThis: showThis
}

showThis(); // global
o.showThis(); // global

我們看到,改爲箭頭函數後,不論用什麼引用來調用它,都不影響它的 this 值。

class C {
    showThis() {
        console.log(this);
    }
}
var o = new C();
var showThis = o.showThis;

showThis(); // undefined
o.showThis(); // o

創建一個類並實例化以後再次調用獲得的結果又是不同的

this關鍵字的機制

JavaScript 標準定義了 [[thisMode]] 私有屬性。[[thisMode]] 私有屬性有三個取值。

  • lexical:表示從上下文中找 this,這對應了箭頭函數。
  • global:表示當 this 爲 undefined 時,取全局對象,對應了普通函數。
  • strict:當嚴格模式時使用,this 嚴格按照調用時傳入的值,可能爲 null 或者 undefined。

class中的函數this行爲與其他函數不一樣正是因爲class設計成了默認爲strict模式執行。在strict模式下普通函數與class中的函數行爲一致。

"use strict"
function showThis(){
    console.log(this);
}

var o = {
    showThis: showThis
}

showThis(); // undefined
o.showThis(); // o

而箭頭函數中this的指向當前上下文中的this,所以下例中foo函數內部潛逃的剪頭函數this與foo相同,o.foo()中this爲對象o所以內部剪頭函數的this均爲o。

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

o.foo()()(); // o, o, o

操作this的內置函數

JavaScript中提供了apply call bind三個方法來改變函數中this的指向(不清楚用法自行百度)。三個方法只針對普通函數有效,箭頭函數、class均不會報錯,但是無法改變this,可以傳參。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章