JavaScript中的this指向問題對於web前端入行不深的人來講是個比較複雜的問題。特寫此文章來記錄今天遇到的關於匿名函數中this指向問題的思考和感悟。前端
今天在研究函數防抖場景時看到以下代碼:web
function debounce(fn, delay) { var timer; // 維護一個 timer return function () { var _this = this; // 取debounce執行做用域的this var args = arguments; if (timer) { clearTimeout(timer); } timer = setTimeout(function () { fn.apply(_this, args); // 用apply指向調用debounce的對象,至關於_this.fn(args); }, delay); }; }
其中有一段代碼是 var _this = this
這段代碼出如今由return返回的匿名函數中,這個時候我就有些懵逼了,由於根據我匱乏的js知識,這裏的this應該是指向全局做用域纔對,爲何能像註釋那樣指向debounce執行時的做用域呢?感受以下所寫是否更加合理呢?(事實證實這麼寫確定是不對的)閉包
function debounce(fn, delay) { var timer var _this = this return function() { ... } }
因而我打算用代碼來實測這裏的 debounce執行做用域中的this到底指的是什麼,它會變化嗎?仍是根據個人理解只要是像相似的匿名函數其中的this都是指向全局的呢?app
因而我寫下以下代碼(關鍵部分):
body部分新增一個button標籤函數
`<button>我是button</button>`
script標籤內部代碼以下:this
//函數防抖 function debounce(fn, delay) { var timer; // 維護一個 timer return function () { var _this = this; // 取debounce執行做用域的this var args = arguments; if (timer) { clearTimeout(timer); } timer = setTimeout(function () { fn.apply(_this, args); // 用apply指向調用debounce的對象,至關於_this.fn(args); }, delay); }; } var btn = document.getElementsByTagName('button')[0] btn.onclick= debounce(function() { console.log(this) }, 1000)
點擊按鈕,看看控制檯輸出this究竟是誰,按照我以前的理解輸出的this應該是window全局對象纔對
spa
出乎意料,這裏的this輸出的是button元素,因而我再在上述腳本中新增一個事件綁定:code
window.onclick = debounce(function() { console.log(this) }, 1000)
點擊頁面空白處輸入以下:
此次輸出的就是window了! 看來這裏的this實際是跟debounce函數所返回函數的實際調用者有關,第一次控制檯輸出的是button元素,由於是經過button元素來調用該返回函數,第二次調用者就是widnow,舉這段btn.onclick = dobounce(function() {console.log(this)}, 1000)
代碼的例子:對象
btn.onclick = function() { var _this = this; // 取debounce執行做用域的this var args = arguments; if (timer) { clearTimeout(timer); } //由於閉包的存在timer仍是取的debounce中的timer timer = setTimeout(function () { fn.apply(_this, args); // 用apply指向調用debounce的對象,至關於_this.fn(args); }, delay); }
那麼這裏的this指向的就是button元素了,爲何呢,emmm寫了太多了,打算專門再寫一篇總結來延伸this的指向問題,今天的總結到此結束!blog