天天看點

前端學習筆記(5) - JavaScript中this 關鍵字的機制JavaScript中有幾種函數不同函數this關鍵字的行為this關鍵字的機制操作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,可以傳參。

繼續閱讀