1. 程式人生 > >徹底理解this指向-----實例分析

徹底理解this指向-----實例分析

問題 con tar log color pre window對象 href ret

this的指向在函數創建的時候是決定不了的,在調用的時候才能決定,誰調用的就指向誰,一定要搞清楚這個。

情況1:如果一個函數中有this,但是它沒有被上一級的對象所調用,那麽this指向的就是window,

這裏需要說明的是在js的嚴格版中this指向的不是window,但是我們這裏不探討嚴格版的問題。

情況2:如果一個函數中有this,這個函數有被上一級的對象所調用,那麽this指向的就是上一級的對象。

情況3:如果一個函數中有this,這個函數中包含多個對象,盡管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象。

例1:針對情況1給出下面的例子

1
function 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指向-----實例分析