徹底理解this指向-----實例分析
this的指向在函數創建的時候是決定不了的,在調用的時候才能決定,誰調用的就指向誰,一定要搞清楚這個。
情況1:如果一個函數中有this,但是它沒有被上一級的對象所調用,那麽this指向的就是window,
這裏需要說明的是在js的嚴格版中this指向的不是window,但是我們這裏不探討嚴格版的問題。
情況2:如果一個函數中有this,這個函數有被上一級的對象所調用,那麽this指向的就是上一級的對象。
情況3:如果一個函數中有this,這個函數中包含多個對象,盡管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象。
例1:針對情況1給出下面的例子
1function a(){ 2 var user = "軒悅"; 3 console.log(this.user); //undefined 4 console.log(this); //Window 5 } 6 a();
this最終指向的是調用它的對象,這裏的函數a實際是被Window對象所點出來的。
例2:針對情況2給出例子
var o = { user:"軒悅", fn:function(){ console.log(this.user); //軒悅 } } o.fn();
這裏的this指向的是對象o,因為你調用這個fn是通過o.fn()執行的,那自然指向就是對象o。
例3:針對情況3給出例子
var o = { user:"軒悅", fn:function(){ console.log(this.user); //軒悅 } } window.o.fn();
例3和例2的代碼幾乎是一樣的,但是這裏的this為什麽不是指向window,如果按照上面的理論,最終this指向的是調用它的對象。
這裏先說個而外話,window是js中的全局對象,我們創建的變量實際上是給window添加屬性,所以這裏可以用window點o對象。
原因就是情況3------------this只會指向它的上一級對象,不管這個對象中有沒有this要的東西。
例4:為了說明上面的問題,我們繼續看一下例子
var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //12 } } } o.b.fn();
將對象b中的變量去掉:如下
var o = { a:10, b:{ fn:function(){ console.log(this.a); //undefined } } } o.b.fn();
可以看到:盡管對象b中沒有屬性a,這個this指向的也是對象b,因為this只會指向它的上一級對象,不管這個對象中有沒有this要的東西。
-------------------------------------------------------------------------------------------分界線-----------------------------------------------------------------------------------------------------------------
下面看一些特殊情況:
例5 : 調用但沒有立即執行版this
var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //undefined console.log(this); //window } } } var j = o.b.fn; j();
可以看到,上面的this並沒有指向上一級對象b。
this永遠指向的是最後調用它的對象,也就是看它執行的時候是誰調用的。
在例5代碼中,雖然函數fn是被對象b所引用,但是在將fn賦值給變量j的時候並沒有執行,所以最終指向的是window。
這和例4是不一樣的,例4是直接執行了fn。
例6:構造函數版this
function Fn(){ this.user = "軒悅"; } var a = new Fn(); console.log(a.user); //軒悅
這裏之所以對象a可以點出函數Fn裏面的user是因為new關鍵字可以改變this的指向,將這個this指向對象a。
為什麽我說a是對象,因為用了new關鍵字就是創建一個對象實例,理解這句話可以想想我們的例子4,
我們這裏用變量a創建了一個Fn的實例(相當於復制了一份Fn到對象a裏面),此時僅僅只是創建,並沒有執行,而調用這個函數Fn的是對象a.
那麽this指向的自然是對象a,那麽為什麽對象a中會有user,因為你已經復制了一份Fn函數到對象a中,用了new關鍵字就等同於復制了一份。
除了上面的這些以外,我們還可以自行改變this的指向,比如JavaScript中call,apply,bind方法可以手動更改this的指向。
例7:return版this
function fn() { this.user = ‘軒悅‘; return {}; } var a = new fn; console.log(a.user); //undefined
function fn() { this.user = ‘軒悅‘; return function(){}; } var a = new fn; console.log(a.user); //undefined
function fn() { this.user = ‘軒悅‘; return 1; } var a = new fn; console.log(a.user); //軒悅
function fn() { this.user = ‘軒悅‘; return undefined; } var a = new fn; console.log(a.user); //軒悅
總結:如果返回值是一個對象,那麽this指向的就是那個返回的對象,如果返回值不是一個對象那麽this還是指向函數的實例。
但是null是一個特例,雖然null也是對象,但是在這裏this還是指向那個函數的實例,因為null比較特殊。
function fn() { this.user = ‘軒悅‘; return null; } var a = new fn; console.log(a.user); //軒悅
徹底理解this指向-----實例分析