博客 / 詳情

返回

徹底搞懂js中this指向

想要理解this,先記住以下兩點:

1:this永遠指向一個對象;

2:this的指向完全取決於函數調用的位置;

①:如果一個函數中有this,但是它沒有被上一級的對象所調用,那麼this指向的就是window,這裏需要説明的是在js的嚴格版中this指向的不是window,但是我們這裏不探討嚴格版的問題(在嚴格版中的默認的this不再是window,而是undefined。)

function fun(){
    console.log(this.s);
}
​
var obj = {
    s:'1',
    f:fun
}
​
var s = '2';
​
obj.f(); //1
fun(); //2

另外還有兩種種特殊情況:

第一種:當this遇到return

1

function fn()  
{  
    this.user = '二狗子';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined

2.

function fn()  
{  
    this.user = '二狗子';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined

3.

function fn()  
{  
    this.user = '二狗子';  
    return 1;
}
var a = new fn;  
console.log(a.user); //二狗子

4.

function fn()  
{  
    this.user = '二狗子';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //二狗子

5.


function fn()  
{  
    this.user = '二狗子';  
    return null;
}
var a = new fn;  
console.log(a.user); //二狗子

總結:如果返回值是一個對象,那麼this指向的就是那個返回的對象,如果返回值不是一個對象那麼this還是指向函數的實例。
還有一點就是雖然null也是對象,但是在這裏this還是指向那個函數的實例,因為null比較特殊。

this使用最頻繁的幾種情況做一個總結,最常見的基本就是以下5種:
對象中的方法,事件綁定 ,構造函數 ,定時器,函數對象的call()、apply() 方法;

事件綁定中的this

行內綁定事件:

當事件觸發時,屬性值就會作為JS代碼被執行,當前運行環境下沒有clickFun函數,因此瀏覽器就需要跳出當前運行環境,在整個環境中尋找一個叫clickFun的函數並執行這個函數,所以函數內部的this就指向了全局對象window;如果不是一個函數調用,直接在當前節點對象環境下使用this,那麼顯然this就會指向當前節點對象;

<input type="button" value="按鈕" onclick="clickFun()">
<script>
    function clickFun(){
    console.log(this) //打印window對象
        this // 此函數的運行環境在全局window對象下,因此this指向window;
    }
</script>
​
<input type="button" value="按鈕1" onclick="clickFun">
<input type="button" value="按鈕2" onclick="clickFun"><!--打印input節點-->
<!-- 運行環境在節點對象中,因此this指向本節點對象 -->

動態綁定與事件監聽:

<input type="button" value="按鈕" id="btn">
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        this ;  // this指向本節點對象
    }
</script>

構造函數中的this

function Pro(){
    this.x = '1';
    this.y = function(){};
}
var p = new Pro();

image.png
new 一個構造函數並執行函數內部代碼的過程就是這個五個步驟,當 JS 引擎指向到第3步的時候,會強制的將this指向新創建出來的這個對象;

window定時器中的this

var obj = {
    fun:function(){
        this ;
    }
}
​
setInterval(obj.fun,1000);      // this指向window對象
setInterval('obj.fun()',1000);  // this指向obj對象

setInterval() 是window對象下內置的一個方法;
在上面的代碼中,setInterval(obj.fun,1000) 的第一個參數是obj對象的fun ,因為 JS 中函數可以被當做值來做引用傳遞,實際就是將這個函數的地址當做參數傳遞給了 setInterval 方法,換句話説就是 setInterval 的第一參數接受了一個函數,那麼此時1000毫秒後,函數的運行就已經是在window對象下了,也就是函數的調用者已經變成了window對象,所以其中的this則指向的全局window對象
而在 setInterval('obj.fun()',1000) 中的第一個參數,實際則是傳入的一段可執行的 JS 代碼;1000毫秒後當 JS 引擎來執行這段代碼時,則是通過 obj 對象來找到 fun 函數並調用執行,那麼函數的運行環境依然在 對象 obj 內,所以函數內部的this也就指向了 obj 對象;

函數對象的call()、apply() 方法

函數作為對象提供了call(),apply() 方法,他們也可以用來調用函數,這兩個方法都接受一個對象作為參數,用來指定本次調用時函數中this的指向

call()方法

var lisi = {names:'lisi'};
var zs = {names:'zhangsan'};
function f(age){
    console.log(this.names);
    console.log(age);
    
}
f(23);//undefined
​
//將f函數中的this指向固定到對象zs上;
f.call(zs,32);//zhangsan

apply()方法

var lisi = {name:'lisi'}; 
var zs = {name:'zhangsan'}; 
function f(age,sex){
    console.log(this.name+age+sex); 
}
//將f函數中的this指向固定到對象zs上;
f.apply(zs,[23,'nan']);

注意:call和apply的作用一致,區別僅僅在函數實參參數傳遞的方式上;
這個兩個方法的最大作用基本就是用來強制指定函數調用時this的指向;

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.