以前總結了this的一些常見綁定狀況(【前端工程師手冊】JavaScript之this的筆記),可是還有一些沒有說到,今天繼續學習一下。前端
先說結論:箭頭函數沒有本身的this,它是根據外層(函數或者全局,後面會說到箭頭函數做爲某個對象的方法時的狀況)做用域來決定this,箭頭函數能夠像 bind(..) 同樣確保函數的 this 被綁定到指定對象,也就是說它在運行中不會丟失this,它的this是在聲明箭頭函數時就決定了。es6
var name = 'out' function test(){ this.name = 'in'; setTimeout(function(){ console.log(this.name) },1000) } new test() // 1秒後打印'out'
上面這個是es5中常見的this問題,計時器1s後運行匿名函數,this已經丟失了,因而默認綁定到了window上。
以前的經典處理方法是:segmentfault
var name = 'out' function test(){ this.name = 'in'; var self = this; setTimeout(function(){ console.log(self.name) },1000) } new test() // 1秒後打印'in'
顯式的使用self來保存住正確的this,防止this丟失。
其實這些均可以使用箭頭函數來實現:前端工程師
var name = 'out' function test(){ this.name = 'in'; setTimeout(() => { console.log(this.name) },1000) } new test() // 1秒後打印'in'
在上面的代碼片斷中,箭頭函數內部的this在聲明期間就綁定爲外層函數的this,且在運行過程當中不會被修改。app
var Agumon = () => { this.name = 'agumon' } var agumon = new Agumon() // Uncaught TypeError: Agumon is not a constructor
使用箭頭函數去當作構造函數來new對象會直接報錯,不過這個也好理解,由於箭頭函數並無本身的this,new操做中有用到this的步驟它搞不定。函數
function foo() { // 返回一個箭頭函數 return (a) => { console.log( this.a ); }; } var obj1 = { a:2 }; var obj2 = { a:3}; var bar = foo.call( obj1 ); bar.call( obj2 ); // 2, 不是3
上面的代碼片斷顯式的使用call來想把foodethis綁定到obj1,然而並不奏效,由於箭頭函數的this並不會在運行時再被改變。學習
var Foo = () => {}; console.log(Foo.prototype); // undefined
箭頭函數是沒有原型的this
var obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log( this.i, this) } } obj.b(); // undefined obj.c(); // 10, Object {...}
剛剛說了根據外層做用域來決定this,上面代碼片斷中的對象obj還不足以生成做用域,再往上就是全局做用域了,因此this被綁定爲window。
參考資料:
MDN-箭頭函數
《你不知道的JavaScript-上卷》es5