淺談箭頭函數和setTimeout中的this
阿新 • • 發佈:2019-04-05
同學 答案 .... col 箭頭 function 一個 個人喜歡 文章
箭頭函數會改變this的指向,這個大家看文檔都看到過,可是有沒有具體理解呢?
我發現自己應該可能大概是......emmmm,然後我整理了一遍,加強一下概念吧
順帶再講一下setTimeout這個函數改寫this的概念
首先分別講一下兩位主角
- 箭頭函數:都2019年了,大家肯定不陌生了,用法很簡單,可以自行百度,箭頭函數有一個很大的特性是會改寫內部的this指向,那麽實際運用的過程中你考慮過註意過這個問題嗎?箭頭函數內部的this會指向聲明箭頭函數時所在作用域的this(劃重點!!接下來要記住!)
- setTimeout:大家肯定都用過了,它的第一個參數是一個方法,傳入的這個方法內部的this會被改寫指向window(劃重點!!接下來要記住!)
一貫風格,我們上代碼來看問題
// 先給window加一個id,以便於確認之後this的指向 window.id = 0; // 聲明一個函數fn const fn = { id: 1, say: function() { console.log(‘id:‘, this.id); }, sayArrow: () => { console.log(‘id:‘, this.id); }, say1: function() { setTimeout(function() { console.log(‘id:‘, this.id); }, 1000); }, say2: function() { let that = this; setTimeout(function() { console.log(‘id:‘, that.id); }, 1000); }, say3: function() { setTimeout(() => { console.log(‘id:‘, this.id); }, 1000); }, say4: () => { setTimeout(() => { console.log(‘id:‘, this.id); }, 1000); }, say5: () => { setTimeout(function() { console.log(‘id:‘, this.id); }, 1000); }, };
好了,接下來大家來做題,不要做暈了哈
fn.say(); fn.sayArrow(); setTimeout(fn.say, 1000); setTimeout(fn.sayArrow, 1000); setTimeout(() => fn.say(), 1000); setTimeout(() => fn.sayArrow(), 1000); fn.say1(); fn.say2(); fn.say3(); fn.say4(); fn.say5();
以上各自輸出什麽呢?接下來核對下答案,如果全對,那ojbk了
1 0 0 0 1 0 0 1 1 0 0
如果覺得自己可能沒摸透,可以多包幾層作用域再試試
接下來看代碼講原因!
fn.say(); /* 結果: 1 原因: 通過fn調用的say, say是 函數聲明, this指向fn,輸出的是fn.id */ fn.sayArrow(); /* 結果: 0 原因: 通過fn調用的say, say是 箭頭函數聲明, this指向箭頭函數聲明時作用域的this,也就是this指向window,輸出的是window.id */ setTimeout(fn.say, 1000); /* 結果: 0 原因: 通過setTimeout調用, setTimeout改寫所傳函數的this, 也就是this指向window,輸出的是window.id */ setTimeout(fn.sayArrow, 1000); /* 結果: 0 原因: 通過setTimeout調用, setTimeout改寫所傳函數的this, 也就是this指向window,輸出的是window.id */ setTimeout(() => fn.say(), 1000); /* 結果: 1 原因: 通過setTimeout調用, 但是fn.say()是被箭頭函數包裹,所以fn.say()調用不受this改變的影響,原因參考第一句輸出 ps: 等同於 setTimeout(function () { fn.say(); } , 1000); */ setTimeout(() => fn.sayArrow(), 1000); /* 結果: 0 原因: 同上雷同,具體原因可參考第二句輸出 ps: 等同於 setTimeout(function () { fn.sayArrow(); } , 1000); */ fn.say1(); /* 結果: 0 原因: setTimeout改寫函數內部的this, 使其指向window, 輸出window.id */ fn.say2(); // 1 /* 結果: 1 原因: setTimeout雖然改寫函數內部的this,但是輸出的是that.id,這個that在setTimout外面聲明,指向的是fn,所以輸出fn.id */ fn.say3(); // 1 /* 結果: 1 原因: fn.say3函數其內部的this指向的fn,而setTimeout內部傳了一個箭頭函數,箭頭函數內部中的this就指向了fn.say3內的this,也就是fn,最後輸出fn.id */ fn.say4(); // 0 /* 結果: 0 原因: fn.say4這個函數本身就是使用箭頭函數聲明,其內部的this指向的是箭頭函數聲明時所在的作用域,即window,而且setTimeout也是傳了一個箭頭函數,這裏面的this指向外層箭頭函數內部中的this,傳引用也指向了window,最後輸出window.id */ fn.say5(); // 0 /* 結果: 0 原因: fn.say5用箭頭函數聲明,其內部的this指向window,而且setTimeout也會改寫內部this指向window,最後輸出window.id */
其實有一些調用其根本原因是相同的,但是我個人喜歡各個方面去驗證一下,加深一下印象也好,勿噴
附帶說一嘴,如果有同學在學node, node內部是沒有window對象的,window是瀏覽器規範,所以具體情況看你在哪裏用了,不過概念是差不多的
寫完覺得這篇文章真的是淺談...好low啊哈哈哈哈,寫給自己看!
淺談箭頭函數和setTimeout中的this