this四大繫結規則

2021-09-19 23:54:45 字數 3683 閱讀 8310

談到this繫結規則要先找到函式執行過程中的呼叫位置。

呼叫位置就是函式在**中被呼叫的位置。這就涉及分析呼叫棧(就是為了到達當前執行位置所呼叫的所有函式)。呼叫位置就在當前正在執行的函式的前乙個呼叫中

那什麼是呼叫棧和呼叫位置呢?

//1.呼叫棧和呼叫位置

function

baz(

)function

bar(

)function

foo(

)baz()

;//<-- baz的呼叫位置

呼叫棧是baz->bar->foo,當呼叫foo()時呼叫位置就是bar(),可以簡單理解為在bar()中呼叫foo().

注意是如何(從呼叫棧中)分析出真正的呼叫位置的,因為它決定了this的繫結。

this有四大繫結規則,下面來仔細看看這四大規則。

function

foo(

)var a=2;

foo();

//2

foo()是直接使用不帶任何修飾的函式引用進行呼叫的,因此只能使用預設繫結,無法應用其他規則

//嚴格模式下全域性物件將無法使用預設繫結,this會繫結到undefined. 嚴格模式下與foo()的呼叫位置無關

function

foo(

)var a=2;

foo();

//undefined

function

foo(

)var obj=

;obj.

foo();

//2

呼叫位置會使用obj上下文來引用函式。當foo()被呼叫時,它的落腳點指向obj物件。當函式引用有上下文物件時,隱式繫結規則會把函式呼叫中的this繫結到這個上下文物件,因此this.a和obj.a是一樣的。

物件屬性引用鏈中只有最頂層或者說最後一層會影響呼叫位置。舉例來說:

function

foo(

)var obj2=

;var obj1=

;obj1.obj2.

foo();

//42

隱式丟失

乙個最常見的this繫結問題就是被隱式繫結的函式會丟失繫結物件,也就是說它會應用預設繫結,從而把this繫結到全域性物件或者undefined上,取決於是否是嚴格模式。

//隱式丟失

function

foo(

)var obj=

;var bar=obj.foo;

//函式別名!bar引用的是foo函式本身

var a=

"hello febby"

;//a是全域性物件屬性

bar();

//hello febby

雖然bar只是obj.foo的乙個引用,實際上,它引用的是foo函式本身,因此此時的bar()其實是乙個不帶任何修飾的函式呼叫,因此應用了預設繫結

同時注意區分下面這種呼叫方式

function

foo(

)var obj=

;var bar=obj.

foo();

//繫結到obj上

var a=

"hello febby"

;//a是全域性物件屬性

// bar; //2

console.

log(bar)

;//2

再來思考一下下面這段**:

function

foo(

)function

dofoo

(fn)

var obj=

;var a=

"hello febby"

;//a是全域性物件屬性

dofoo

(obj.foo)

;//hello febby

引數傳遞其實就是一種隱式賦值,因此我們傳入函式時也會被隱式賦值,所以結果跟上面一樣。

如果把函式傳入語言內建的函式而不是傳入自己宣告的函式,結果是一樣的。

function

foo(

)var obj=

;var a=

"hello febby"

;//a是全域性物件屬性

settimeout

(obj.foo,

100)

;//hello febby

//js環境中內建的settimeout()函式實現與下面偽**類似

function

settimeout

(fn,delay)

//顯式繫結

function

foo(

)var obj=

;foo.

call

(obj)

;//2

foo.

(obj)

;//2

硬繫結可以解決丟失繫結問題。

function

foo(

)var obj=

;var

bar=

function()

;bar()

;//2

settimeout

(bar,

100)

;//2

//硬繫結的bar不可能再修改它的this

bar.

call

(window)

//2

我們建立了bar(),並在它的內部手動呼叫了foo.call(obj),因此強制把foo的this繫結到了obj上。無論之後怎麼呼叫函式bar,它總會手動在obj上呼叫 foo。這種繫結是一種顯式的強制繫結,因此我們稱之為硬繫結

new繫結

在js中,建構函式只是一些使用new操作符是被呼叫的函式。它們並不屬於某個類,也不會例項化乙個類。實際上,它們只是被new操作符呼叫的普通函式而已。

使用new來呼叫函式,或者說發生構造函式呼叫時,會自動執行下面的操作。

建立(或者說構造)乙個全新的物件。

這個新物件會被執行[[原型]]連線。

這個新物件會繫結到函式呼叫的this。

如果函式沒有返回其他物件,那麼new表示式中的函式會自動返回這個新物件。

//new繫結

function

foo(a)

var bar=

newfoo(2

);console.

log(bar.a)

;//2

使用new來呼叫foo(…)時,會構造乙個新物件並把它繫結到foo(…)呼叫中的this。

以上便是this四大繫結規則的總結,希望可以幫到大家。

具體用法傳送門:

this學習(三)this繫結規則的優先順序

目錄 一 顯式繫結 vs 隱式繫結 二 new繫結 vs 隱式繫結 三 顯示繫結 vs new繫結 四 總結 在前面的學習中,有預設繫結 顯式繫結 隱式繫結 new繫結,這4種規則當中,預設繫結的優先順序一定是最低的,那麼其它三個規則的優先順序到底是怎麼樣的呢?例子 function foo var...

2 3 this 繫結規則的優先順序

上篇 2.2this全面解析 了解到函式呼叫中this繫結的四條規則,找到函式的呼叫位置並判斷應當應用哪條規則。這篇學習假設某個呼叫位置可以應用多條規則,就必須給這些規則設定優先順序。毫無疑問,預設繫結的優先順序是四條規則中最低的,所以可以先不考慮它。function foo var obj1 va...

解讀IT架構管理中的四大重要規則

計算機系統的架構非常重要。不太合適的引用已故的green bay packers的傳奇教練vince lombardi話說,架構不是所有的事情,但是它是唯一的事情。或者曲解另乙個古老的說法,電腦程式潮起潮落,不好的架構永遠存在。通過觀察許多it部門的努力得出上述結論的。這些it部門的架構不能迅速改變...