javascript this指向相關(guān)問題及改變方法
在學(xué)習(xí)javascript中我們往往會被this的指向問題弄的頭昏轉(zhuǎn)向,今天我們就來學(xué)習(xí)一下this的指向問題,和改變this指向的方法。
一.this的指向問題
在學(xué)習(xí)this的指向問題之前我們需要明白兩點:
1:this永遠(yuǎn)指向一個對象;
2:this的指向完全取決于函數(shù)調(diào)用的位置;
針對上面第一點我們能很好理解,因為在javascript中一切都是對象。第二點其實也是好理解,當(dāng)函數(shù)調(diào)用的位置不同是,this的指向的對象就不同,所以可以說this的指向可以動態(tài)變換的,下面我們先通過一個簡單的例子來看一下this的指向是變換的
<script> function fun(){ console.log(this.name); } var change={ name:'hello', f:fun } var name ='world' var result=change.f()//hello fun();//world </script>
通過上述例子我們可以很清楚的看到this的指向的變化,因為有一個函數(shù)在對象change里面,所以this就是指向的函數(shù)外部的對象,所以輸出了hello。
想必看完上述例子后大家對this的動態(tài)指向切換有了一定的了解。
那么接下來,我們對this使用最頻繁的幾種情況做一個總結(jié),最常見的基本就是以下3種:
對象中的方法,事件綁定 ,構(gòu)造函數(shù) ,定時器
前兩個就不必多說了,我們看一下定時器中的this指向問題,
var obj = { fun:function(){ this ; } } setInterval(obj.fun,1000); // this指向window對象 setInterval('obj.fun()',1000); // this指向obj對象
setInterval() 是window對象下內(nèi)置的一個方法,接受兩個參數(shù),第一個參數(shù)允許是一個函數(shù)或者是一段可執(zhí)行的 JS 代碼,第二個參數(shù)則是執(zhí)行前面函數(shù)或者代碼的時間間隔;
在上面的代碼中,setInterval(obj.fun,1000) 的第一個參數(shù)是obj對象的fun ,因為 JS 中函數(shù)可以被當(dāng)做值來做引用傳遞,實際就是將這個函數(shù)的地址當(dāng)做參數(shù)傳遞給了 setInterval 方法,換句話說就是 setInterval 的第一參數(shù)接受了一個函數(shù),那么此時1000毫秒后,函數(shù)的運行就已經(jīng)是在window對象下了,也就是函數(shù)的調(diào)用者已經(jīng)變成了window對象,所以其中的this則指向的全局window對象;
而在 setInterval('obj.fun()',1000) 中的第一個參數(shù),實際則是傳入的一段可執(zhí)行的 JS 代碼;1000毫秒后當(dāng) JS 引擎來執(zhí)行這段代碼時,則是通過 obj 對象來找到 fun 函數(shù)并調(diào)用執(zhí)行,那么函數(shù)的運行環(huán)境依然在 對象 obj 內(nèi),所以函數(shù)內(nèi)部的this也就指向了 obj 對象;
除了這些我們還需要理解三個可以改變this指向的函數(shù),包括箭頭函數(shù),call(),apply()
箭頭函數(shù):官方有解釋,箭頭函數(shù)引入的其中一個原因,就是其不綁定this;在箭頭函數(shù)中,箭頭函數(shù)的this被設(shè)置為封閉的詞法環(huán)境的,換句話說,箭頭函數(shù)中的this取決于該函數(shù)被創(chuàng)建時的環(huán)境。
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
// 接著上面的代碼
// 作為對象的一個方法調(diào)用
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true
// 嘗試使用call來設(shè)定this
console.log(foo.call(obj) === globalObject); // true
// 嘗試使用bind來設(shè)定this
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
無論如何,foo 的 this 被設(shè)置為他被創(chuàng)建時的環(huán)境(在上面的例子中,就是全局對象)。這同樣適用于在其他函數(shù)內(nèi)創(chuàng)建的箭頭函數(shù):這些箭頭函數(shù)的this被設(shè)置為封閉的詞法環(huán)境的。
// 創(chuàng)建一個含有bar方法的obj對象, // bar返回一個函數(shù), // 這個函數(shù)返回this, // 這個返回的函數(shù)是以箭頭函數(shù)創(chuàng)建的, // 所以它的this被永久綁定到了它外層函數(shù)的this。 // bar的值可以在調(diào)用中設(shè)置,這反過來又設(shè)置了返回函數(shù)的值。 var obj = { bar: function() { var x = (() => this); return x; } }; // 作為obj對象的一個方法來調(diào)用bar,把它的this綁定到obj。 // 將返回的函數(shù)的引用賦值給fn。 var fn = obj.bar(); // 直接調(diào)用fn而不設(shè)置this, // 通常(即不使用箭頭函數(shù)的情況)默認(rèn)為全局對象 // 若在嚴(yán)格模式則為undefined console.log(fn() === obj); // true // 但是注意,如果你只是引用obj的方法, // 而沒有調(diào)用它 var fn2 = obj.bar; // 那么調(diào)用箭頭函數(shù)后,this指向window,因為它從 bar 繼承了this。 console.log(fn2()() == window); // true
call和apply方法:將一個對象作為call或者apply的第一個參數(shù),this將會被綁定到這個參數(shù)對象上
var obj = {parent:'男'}; var parent = '28'; function child(obj){ console.log(this.parent); } child(); // 28 child.call(obj); //男 child.apply(obj); //男
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面
本文主要介紹了微信小程序?qū)崿F(xiàn)搜索功能并跳轉(zhuǎn)搜索結(jié)果頁面,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12JavaScript中Object和Function的關(guān)系小結(jié)
JavaScript 中 Object 和 Function 的關(guān)系是微妙的,他們互為對方的一個實例。2009-09-09