js中的this指向和改變this指向的方法

2021-10-01 05:57:47 字數 4567 閱讀 3854

徹底理解js中this的指向,不必硬背。

首先必須要說的是,this的指向在函式定義的時候是確定不了的,只有函式執行的時候才能確定this到底指向誰,實際上this的最終指向的是那個呼叫它的物件(這句話有些問題,後面會解釋為什麼會有問題,雖然網上大部分的文章都是這樣說的,雖然在很多情況下那樣去理解不會出什麼問題,但是實際上那樣理解是不準確的,所以在你理解this的時候會有種琢磨不透的感覺),那麼接下來我會深入的**這個問題。

例子一:

function a()

a();

按照我們上面說的this最終指向的是呼叫它的物件,這裡的函式a實際是被window物件所點出來的,下面的**就可以證明。

function a()

window.a();

和上面**一樣吧,其實alert也是window的乙個屬性,也是window點出來的。

例子二

var o = 

}o.fn();

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

其實例子1和例子2說的並不夠準確,下面這個例子就可以推翻上面的理論。

如果要徹底的搞懂this必須看接下來的幾個例子

例子3:

var o = 

}window.o.fn();

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

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

var o = 

}}o.b.fn();

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

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

var o = 

}}o.b.fn();

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

還有一種比較特殊的情況,例子4:

var o = 

}}var j = o.b.fn;

j();

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

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

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

建構函式版this:

function fn()

var a = new fn();

console.log(a.user); //追夢子

這裡之所以物件a可以點出函式fn裡面的user是因為new關鍵字可以改變this的指向,將這個this指向物件a,為什麼我說a是物件,因為用了new關鍵字就是建立乙個物件例項,理解這句話可以想想我們的例子3,我們這裡用變數a建立了乙個fn的例項(相當於複製了乙份fn到物件a裡面),此時僅僅只是建立,並沒有執行,而呼叫這個函式fn的是物件a,那麼this指向的自然是物件a,那麼為什麼物件fn中會有user,因為你已經複製了乙份fn函式到物件a中,用了new關鍵字就等同於複製了乙份。

更新乙個小問題當this碰到return時

function fn()  

; }

var a = new fn;

console.log(a.user); //undefined

再看乙個

function fn()  ;}

var a = new fn;

console.log(a.user); //undefined

再來

function fn()  

var a = new fn;

console.log(a.user); //追夢子

function fn()  

var a = new fn;

console.log(a.user); //追夢子

什麼意思呢?

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

function fn()  

var a = new fn;

console.log(a); //fn

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

function fn()  

var a = new fn;

console.log(a.user); //追夢子

知識點補充:

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

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

function fn()

var a = new fn();

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

一般用來指定this的環境,在沒有學之前,通常會有這些問題。

var a = 

}var b = a.fn;

b(); //undefined

我們是想列印物件a裡面的user卻列印出來undefined是怎麼回事呢?如果我們直接執行a.fn()是可以的。

var a = 

}a.fn(); //追夢子

這裡能夠列印是因為,這裡的this指向的是函式a,那為什麼上面的不指向a?我們如果需要了解this的指向問題,請看徹底理解js中this的指向,不必硬背這篇文章。

雖然這種方法可以達到我們的目的,但是有時候我們不得不將這個物件儲存到另外的乙個變數中,那麼就可以通過以下方法。

1、call()

var a = 

}var b = a.fn;

b.call(a);

通過在call方法,給第乙個引數新增要把b新增到哪個環境中,簡單來說,this就會指向那個物件。

call方法除了第乙個引數以外還可以新增多個引數,如下:

var a = 

}var b = a.fn;

b.call(a,1,2);

var a = 

}var b = a.fn;

var a = 

}var b = a.fn;

或者

var a = 

}var b = a.fn;

var arr = [500,20];

var a = 

}}var b = a.fn;

3、bind()

先來說說它們的不同吧。

var a = 

}var b = a.fn;

b.bind(a);

var a = 

}var b = a.fn;

var c = b.bind(a);

console.log(c); //function()

那麼我們現在執行一下函式c看看,能不能列印出物件a裡面的user

var a = 

}var b = a.fn;

var c = b.bind(a);

c();

ok,同樣bind也可以有多個引數,並且引數可以執行的時候再次新增,但是要注意的是,引數是按照形參的順序進行的。

var a = 

}var b = a.fn;

var c = b.bind(a,10);

c(1,2);

function food(name, price)

js中this指向與改變

下面展示一些內聯 片。a code block var foo bar 一 普通函式呼叫 指向windows function f01 f01 直接呼叫 二 構造函式呼叫 指向當前例項物件 function f02 name,age var f2 newf02 阿力 18 三 物件方法呼叫 thsi...

改變JS中的this指向的方法

1.全域性呼叫 函式名 指向 window 2.物件呼叫 物件.函式名 誰呼叫指向誰 前面是誰就指向誰 3.自執行的函式 指向window 4.事件處理函式 指向事件源 5.定時器處理函式 指向事件源 6.函式定義了未呼叫的時候指向不確定 call 語法 函式名.call 你要改變的函式的 this...

js改變this指向的方法

語法 函式.call this,arg1,arg2,arg3,arg4 第乙個引數用來指定函式內部的this指向,後面的引數是函式執行時所需的實參。window.color red document.color yellow var s1 function changecolor changecol...