1. 程式人生 > >淺談箭頭函數和setTimeout中的this

淺談箭頭函數和setTimeout中的this

同學 答案 .... 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