this 相關

2022-11-24 20:41:17 字數 4729 閱讀 4755

對於前端程式媛(員)來說,this這個機制應用的地方是很多的,所以搞懂是必要的,不熟練使用this將遇到一些困惑,下面是一些關於this的學習心得分享,希望大家可以一起學習:

this究竟是指向什麼呢?this是在執行時進行繫結的,並不是在編寫時繫結的,它的上下文取決於函式呼叫時的各種條件,this繫結和函式宣告的位置沒有任何關係,只取決於函式的呼叫方式。

當函式呼叫時,會建立一個執行上下文,這個上下文會記錄函式在**呼叫了,函式的呼叫方法,函式引數等資訊,this就是該上下文的一個屬性,會在函式執行的過程中用到。

函式在執行過程中this是如何繫結的

尋找函式的呼叫位置,其實有的很明顯,而某些程式設計模式會因此函式的真正的呼叫位置

分析呼叫棧

1

function

baz() 78

function

bar()

1415

function

foo()

20 baz(); //

baz的呼叫位置

分析呼叫棧是,決定了this的繫結

this的繫結規則

①預設繫結:獨立函式呼叫  ,在下面的**中,foo()是直接使用不帶任何修飾符的函式引用進行呼叫的,因此只能使用預設繫結

1

function

foo()

4var a = 2;

5 foo(); //

2

但是在嚴格模式下,全域性物件將無法使用預設繫結,因此this會繫結到undefined

1

function

foo()

6var a = 2;

7 foo();

但是有個微妙的非常重要的情況,雖然this的邦定規則完全取決於呼叫位置,但是隻有foo執行在非嚴格模式下是預設繫結才能繫結到全域性物件,但在嚴格模式下,於foo的呼叫位置無關了

1

function

foo()

5var a = 2;

67 (function

() )()

②隱式繫結

1

function

foo()

5var obj =

9 obj.foo();

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

③顯示繫結

1

function

foo()

5var obj =

8 foo.call(obj)

他們的第一個引數是一個物件,不是物件的會利用自己的包裝物件轉換成物件(new number()  ,new string() ,new boolen()等),他們會把這個物件繫結到this,接著在呼叫函式時指定這個this,因為你可以直接指定this的繫結物件,因此我們稱為顯式繫結

④new繫結

1

function

foo(a)

4var bar = new foo(2);

5 console.log(bar.a);//

2

建構函式是使用new操作時會被呼叫的函式。他們並不屬於類,也不會例項化一個類,實際上,甚至不能說他們是一直特殊的函式型別,他們只是用new操作費呼叫的普通函式而已。

使用new來呼叫函式,會自動執行下面操作:

1,建立(或者構造一個)全新的物件

2,這個物件會被執行【原型】連線

3,這個新物件會被繫結到函式呼叫的this,

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

上面的**,使用new呼叫foo()時,我們會構造一個新的物件並把它繫結到foo()呼叫中的this上,new是最後一個可以影響函式呼叫時this邦定行為的方法,我們稱之為new繫結

看一下當遇到return的時候:

1

function

fn()

2; 5}

6var a = new

fn;

7 console.log(a.b); //

undefined

1

function

fn() 2;

5}6var a = new

fn;

7 console.log(a.b); //

undefined

function

fn()

var a = new

fn;

console.log(a.b);

//1

function

fn()

var a = new

fn;

console.log(a.b);

//1

結論是:如果返回值是一個物件,那麼this指向的就是那個返回的物件,如果返回值不是一個物件那麼this還是指向函式的例項。

1

function

fn() 26

var a = new

fn;

7 console.log(a); //

fn

還有一點就是雖然null也是物件,但是在這裡this還是指向那個函式的例項,因為null比較特殊。

1.在嚴格版中的預設的this不再是window,而是undefined。

2.new操作符會改變函式this的指向問題,雖然我們上面講解過了,但是並沒有深入的討論這個問題,網上也很少說,所以在這裡有必要說一下。

1

function

fn()

4var a = new

fn();

5 console.log(a.num); //

1

為什麼this會指向a?首先new關鍵字會建立一個空的物件,然後會自動將this指向這個空物件,這樣的話函式內部的this就會被這個空的物件替代。

總結this理解

再來最後看些this的例子,再來深入總結一下:

再看一下例子:eg1

1

function

a()6 a();

1

function

a()6 window.a();

以上兩個例子,道理一樣,this最終指向的是呼叫它的物件,這裡是全域性物件window

再看一下下面這個例子:eg2

1

var o =6}

7 o.fn();

這裡的this指向的是物件o,因為你呼叫這個fn是通過o.fn()執行的,那自然指向就是物件o,這裡再次強調一點,this的指向在函式建立的時候是決定不了的,在呼叫的時候才能決定,誰呼叫的就指向誰,一定要搞清楚這個。

eg1和eg2說的不夠準確,再看一下下面這個例子:

1

var o =6}

7 window.o.fn();

這段**和上面的那段**幾乎是一樣的,但是這裡的this為什麼不是指向window,如果按照上面的理論,最終this指向的是呼叫它的物件,這裡先說個而外話,window是js中的全域性物件,我們建立的變數實際上是給window新增屬性,所以這裡可以用window點o物件。

這裡先不解釋為什麼上面的那段**this為什麼沒有指向window,我們再來看一段**。

1

var o =8}

9}10 o.b.fn();

這裡同樣也是物件o點出來的,但是同樣this並沒有執行它,那你肯定會說我一開始說的那些不就都是錯誤的嗎?其實也不是,只是一開始說的不準確,接下來我將補充一句話,我相信你就可以徹底的理解this的指向的問題。

情況3:如果一個函式中有this,這個函式中包含多個物件,儘管這個函式是被最外層的物件所呼叫,this指向的也只是它上一級的物件,下面例子可以證明,如果不相信,那麼接下來我們繼續看幾個例子。

eg3:

1

var o =8}

9}10 o.b.fn();

儘管物件b中沒有屬性a,這個this指向的也是物件b,因為this只會指向它的上一級物件,不管這個物件中有沒有this要的東西。

還有一種比較特殊的情況,看下面:eg4

1

var o =9}

10}11var j =o.b.fn;

12 j();

這裡this指向的是window,是不是有些蒙了?其實是因為你沒有理解一句話,這句話同樣至關重要。

this永遠指向的是最後呼叫它的物件,也就是看它執行的時候是誰呼叫的,eg4中雖然函式fn是被物件b所引用,但是在將fn賦值給變數j的時候並沒有執行所以最終指向的是window,這和eg3是不一樣的,eg3是直接執行了fn。

this講來講去其實就是那麼一回事,只不過在不同的情況下指向的會有些不同,上面的總結每個地方都有些小錯誤,也不能說是錯誤,而是在不同環境下情況就會有不同,所以我也沒有辦法一次解釋清楚,只能你慢慢地的去體會。