箭頭函數中this

箭頭函數中this

建議先閱讀本人對于es5中this的詳解 es5中的this詳解

箭頭函數本身是沒有this,導致內部的this就是外層代碼塊的this

ES6的箭頭函數的出現,讓很多剛剛入門的前端很少用到bind()call()apply(),但是還是有必要弄懂this

關鍵詞

  1. 上下文作用域
  2. 綁定上下文

1. 普通函數和箭頭函數比較

  • 不使用call
// 1. 不使用call
var str = 'hcc'
let foo = function() {
  let str = 'yx'
  console.log(this.str) 
}
const foo2 = () => {
  let str = 'hcc2'
  console.log(this.str)
}
foo() //'hcc'
foo2() //'hcc'
// 由于箭頭函數的綁定上下文,所有foo2中的this指向為上級作用域即` window `
  • 變形: 使用call改變this
var str = 'hcc'
let foo = function() {
  let str = 'yx'
  console.log(this.str) 
}
const foo2 = () => {
  let str = 'hcc2'
  console.log(this.str)
}
foo.call({a:1}) //undefined
foo2.call({a:1}) //'hcc'
// 由于箭頭函數本身沒有this,我們通過call改變箭頭函數的this是沒有效果的,foo2中的this還是指向` window `

2.高級函數的比較

  • 箭頭函數和普通函數
const foo = function() {
  return () => {
    console.log(this === window)
  }
}
foo.call({a:1})()  //false
// foo函數中返回一個箭頭函數,對于箭頭函數而言,foo函數就是它的執行上下文,通過call綁定foo的this,所以對于箭頭函數而言,this就是對象{a:1}
const foo2 = () => {
  return () => {
    console.log(this === window)
  }
}
foo2.call({a:1})() //true
// 對于foo2函數而言,自己本身也是一個箭頭函數,返回一個箭頭函數,2個都沒有this,通過call綁定不會生效,所以找到最外層的` window `
  • setTimeout中的this (在箭頭函數之前,setTimeout中的this指向的是全局的window,setTimeout中的箭頭函數沒有this,所以尋找上下文中的this)
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
var id = 21;
foo()  // 21 
// 由于通過foo.call(null)調用foo,foo函數的內部this指向window,setTimeout中的箭頭函數沒有this,所以返回21

foo.call({id: 42}) // 42
// 通過call指定了foo函數執行上下文的this為{id: 42},對于箭頭函數而言,foo就是執行上下文,所以返回42

3. 對象中的使用

var handler = {
  id: '123456',

  init: function() {
    document.addEventListener('click',
      event => this.doSomething(event.type), false);
  },

  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};

handler.init()  //  轉換 handler.init.call(handler)

解析:當我們執行handler中的init方法的時候,init中的this指向的是handler,所以我們在init方法內部使用的所有箭頭函數中的this都會指向handler

拓展

請問下面的代碼之中有幾個this

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id);
      };
    };
  };
}

var f = foo.call({id: 1});

var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1

上面代碼之中,只有一個this,就是函數foothis,所以t1t2t3都輸出同樣的結果。因為所有的內層函數都是箭頭函數,都沒有自己的this,它們的this其實都是最外層foo函數的this

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容