摘要:關于的指向問題算的上是中的一個十分重要的問題了。首先,的指向問題可以用一句話總結就是總是指向調用的對象,也就是說指向誰與函數聲明的位置沒有關系,只與調用的位置有關。此外注意幾種特殊情況,特別是中的箭頭函數。
關于this的指向問題算的上是js中的一個十分重要的問題了。今天把這個問題總結下,加深下自己對this的理解。
首先,this的指向問題可以用一句話總結就是:this總是指向調用的對象,也就是說this指向誰與函數聲明的位置沒有關系,只與調用的位置有關。這是判斷this的一個大體原則,而具體的小原則按照優先級的不同大致可以分為以下幾點:
new方式是優先級最高的一種調用方式,也就是說只要是出現new方式來調用一個函數,this肯定會指向new調用函數新創建的對象。
</>復制代碼
function() thisTo(a){
this.a=a;
}
var data=new thisTo(2); //在這里進行了new綁定
console.log(data.a); //2
2.顯式綁定
顯示綁定指的是通過call()和apply()方法對函數進行的調用,對this影響的優先級僅次于new綁定。
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2
};
thisTo.call(data)); //2
3.隱式綁定
隱式綁定是指通過對象的屬性進行添加,從而調用this所在函數,該方式的優先級在顯示綁定之后。
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2,
foo:thisTo //通過屬性引用this所在函數
};
data.foo(); //2
4.默認綁定
默認綁定是指當上面這三條綁定規則都不符合時采用的綁定規則,默認綁定會把this默認綁定到全局對象中,是優先級最低的綁定規則。
</>復制代碼
function thisTo(){
console.log(this.a);
}
var a=2; //a是全局對象的一個同名屬性
thisTo(); //2
二.this綁定的特殊情況
1.隱式丟失
當進行隱式綁定時,如果進行一次引用賦值或者傳參操作,會造成this的丟失,從而最后將this綁定到全局對象中去。
1.1 引用賦值丟失
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2,
foo:thisTo //通過屬性引用this所在函數
};
var a=3;//全局屬性
var newData=data.foo; //這里進行了一次引用賦值
newData(); // 3
原理:因為newData實際上引用的是foo函數本身,跟data對象沒有任何關系,data對象只是一個中間橋梁。而newData就是一個本身不帶a屬性的對象,自然最后只能把a綁定到全局對象上了。
1.2傳參丟失
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2,
foo:thisTo //通過屬性引用this所在函數
};
var a=3;//全局屬性
setTimeout(data.foo,100);// 3
原理:setTimeout(fn,delay) { fn(); } 實際上fn是一個參數傳遞的引用(fn=data.foo),與引用丟失的原理一樣
1.3 Function.prototype.bind()
為了解決隱式丟失的問題,ES5提供了bind方法,bind()會返回一個硬編碼的新函數,它會把參數設置為this的上下文并調用原始函數。
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2
};
var a=3;
var bar=thisTo.bind(data);
console.log(bar()); //2
2.間接引用
間接引用是指一個定義對象的方法引用另一個對象存在的方法,這種情況下會使得this進行默認綁定。
</>復制代碼
function thisTo(){
console.log(this.a);
}
var data={
a:2,
foo:thisTo
};
var newData={
a:3
}
var a=4;
data.foo(); //2
(newData.foo=data.foo)() //4
原理:newData.foo=data.foo的返回值是目標函數的引用,因此調用的位置實際上是foo(),根據之前的隱式丟失里面說的原則,這里會應用默認綁定。
3.ES6箭頭函數ES6的箭頭函數在this這塊是一個特殊的改進,箭頭函數使用了詞法作用域取代了傳統的this機制,所以箭頭函數無法使用上面所說的這些this優先級的原則,注意的是在箭頭函數中,是根據外層父親作用域來決定this的指向問題。
</>復制代碼
function thisTo(){
setTimeout(function(){
console.log(this.a);
},100);
}
var obj={
a:2
}
var a=3;
thisTo.call(obj); //3
不用箭頭函數,發生隱式丟失,最后的this默認綁定到全局作用域,輸出3。
</>復制代碼
function thisTo(){
setTimeout(()=>{
console.log(this.a);
},100);
}
var obj={
a:2
}
var a=3;加粗文字
thisTo.call(obj); //2
用了箭頭函數,不會發生隱式丟失,this綁定到外層父作用域thisTO(),thisTo的被調用者是obj對象,所以最后的this到obj對象中,輸出2。
如果不用箭頭函數實現相同的輸出,可以采用下面這種方式:
</>復制代碼
function thisTo(){
var self=this; //在當前作用域中捕獲this
setTimeout(function(){
console.log(self.a); //傳入self代替之前的this
},100);
}
var obj={
a:2
}
var a=3;
thisTo.call(obj); //2
三.總結:
this的綁定機制,就是要找到這個函數的直接調用位置,然后應用綁定的四條規則,當出現滿足多個規則時,按照優先級的高低決定最終的綁定規則。此外注意幾種特殊情況,特別是ES6中的箭頭函數。
四.參考書籍:你不知道的JavaScript上卷
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82496.html
摘要:下面只探討在瀏覽器中的指向,有興趣的也可以把后面的例子在中跑一下。 我們知道js中有個全局對象就是window,如果在頂層聲明一個變量如 var a=1 //就相當于window.a=1 同時有了node以后,js也可以在服務端運行了,官方解釋為Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運行環境。通俗說node是一個支持js語法的容器,直接寫js就可...
摘要:是什么這個單詞是一個代詞,所以應該是指代某些東西搞清楚的關鍵之處,就是要搞清楚指代了什么那么到底指代了什么呢就像你平時指著一個蘋果說指著一個香蕉說同樣,也會因為情況的不同而不同在中按照常規理解,的值是什么取決于函數如何被調用然而,的值是什么 1. this是什么 this這個單詞是一個代詞,所以this應該是 指代某些東西搞清楚this的關鍵之處,就是要搞清楚this指代了什么 那么t...
摘要:中指向問題一直是個坑,之前一直是懵懵懂懂的,大概知道一點,但一直不知道各種情況下指向有什么區別,今天親自動手測試了下的指向。這就是我關于學習的總結,希望能給需要的人點幫助,然后有啥不足希望有大神能指點出來。 js中this指向問題一直是個坑,之前一直是懵懵懂懂的,大概知道一點,但一直不知道各種情況下指向有什么區別,今天親自動手測試了下this的指向。 1.在對象中的this對象中的t...
摘要:中指向問題一直是個坑,之前一直是懵懵懂懂的,大概知道一點,但一直不知道各種情況下指向有什么區別,今天親自動手測試了下的指向。這就是我關于學習的總結,希望能給需要的人點幫助,然后有啥不足希望有大神能指點出來。 js中this指向問題一直是個坑,之前一直是懵懵懂懂的,大概知道一點,但一直不知道各種情況下指向有什么區別,今天親自動手測試了下this的指向。 1.在對象中的this對象中的t...
閱讀 1271·2021-11-17 09:33
閱讀 1740·2021-09-09 11:53
閱讀 3200·2021-09-04 16:45
閱讀 1378·2021-08-17 10:12
閱讀 2379·2019-08-30 15:55
閱讀 1776·2019-08-30 15:53
閱讀 2402·2019-08-30 15:52
閱讀 2556·2019-08-29 18:41