說到this,入前端坑的人都知道這是JS初期語言畢竟之路。不少人(我就是)對於this的瞭解很模糊,或者不夠全面。最近打算在反過來在看下es6,在es6中又出現了箭頭函數對於this的理解有多了層認識。因此就在寫一遍來增強本身的認知。前端
在講this以前,咱們先把做用域鏈在複習一下es6
在紅寶書中對做用域鏈的描述有這麼一句話:當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈。做用域鏈的用途是保證對執行環境有權訪問的全部變量和函數的有序訪問
簡單來講,做用域鏈的做用就是在函數使用一個變量的時候,由近到遠的查找有自身內部想最頂層也就是window的做用域中查找。app
咱們做用域鏈明白了,咱們講一下this.函數
this又分傳統this和箭頭函數中的thisthis
傳統this的指向:spa
1.this老是指向它的直接調用者。code
2.在非嚴格模式下當沒有調用者的時候,默認指向最頂層也就是window對象
3.在嚴格模式下('use strict')當沒有調用者的時候,this就是undefinedblog
4.在call、apply、bind綁定的時候,默認指向綁定的對象繼承
箭頭函數中this的指向:
1.箭頭函數自身不包含this,它是繼承與他所處的宿主對象的this。
光寫概念,不說看得煩,我敲得也煩。直接上代碼吧。
實例一:this指向它的直接調用者
var myObj = {
myVal : 3,
myFnc : function(){
console.log(this);
}
}
myObj.myFnc();//myobj
此時myObj調用了因此this指向於myObj;
實例二:非嚴格模式下沒有調用者的時候
function myFnc(){
console.log(this);
}
myFnc();//window
此時,由於沒有調用者,因此this默認指向最頂層也就是window
實例三:嚴格模式下沒有調用者的時候
function myFnc(){
'use strict'
console.log(this);
}
myFnc() //undefined
此時,沒有調用者,又由於當前是嚴格模式因此打印出來的this是undefined
實例四:call、apply、bind綁定的時候function myFnc1(){
function myFuc1(){
console.log(this);
}
function myFnc2(a,b){
console.log(this);
}
myFnc2.call(myFnc1);//myFnc1
此時綁定的就是myFnc1,因此當前this的指向就是myFnc1;
call和apply的綁定機制大體是同樣的,因此就不一一解釋了。
var myObj = {
myFnc :function(){
setTimtout(function(){
console.log(this);
}.bind(this))
}
}
myObj.myFnc();//myObj
由於在定時器函數中,沒有調用者,因此默認指向window。又由於使用bind()方法給回調函數直接綁定了當前this指向,因此當前this指向就是myObj。
是否是感受這麼寫很麻煩,當今的ES6的年代,還用啥bind綁定。若是須要返回當前函數伸手就是一個箭頭函數
實例五:箭頭函數簡易版
var myObj = {
myFnc :function(){
setTimeout(() => {
console.log(this)
})
}
}
myObj.myFnc();
由於箭頭函數繼承的是它的宿主對象的this,也就是繼承的myFnc的this,而myFnc的This指向是myObj,因此打印出來的當前this指向就是myObj;
實例六:箭頭函數嵌套版
var myObj = {
myFnc :function(){
function childFnc(){
setTimeout(() => {
console.log(this)
})
}
childFnc();
}
}
myObj.myFnc();
小小的思考一下。。。
若是你一瞬間就明白的話,那就代表你已經通關了。
由裏到外的分析,你就會發現很簡單。
由於箭頭函數,當前this繼承於它的宿主也就是childFnc。childFnc方法的執行,由於沒有調用者。因此它的this指向的是window。因此當前打印的this指向就是window。
總結:
this指向簡單的說就是誰調用就指向誰,沒調用就指向window(嚴格模式undefined)
當出現箭頭函數內的,就指向宿主元素。