先來看一段代碼:閉包
var func = new function() { this.a = "func"; } // var func2 = function(x) {
// var a = "func2";
// alert(this.a); // func
// alert(x); // func2
// }
// 箭頭函數this指向對象自己
let func2 = x => { let a = 'func2'; alert(this.a) // undefined
alert(x) // func2
} // call改變this指向,將func2的this指向func
func2.call(func, "func2");
1、什麼是箭頭函數,爲何使用箭頭函數?app
箭頭函數就是函數的一種簡寫形式,使用括號包裹參數,跟隨一個=>,緊接着是函數體。函數
ES6中,箭頭函數的引入有兩個方面的做用:一是更簡短的函數書寫,二是對this的詞法解析。this
2、箭頭函數的thisspa
this
值,箭頭函數內的this
值繼承自外圍做用域。
this
指向的固定化,並非由於箭頭函數內部有綁定this
的機制,實際緣由是箭頭函數根本沒有本身的this
,致使內部的this
就是外層代碼塊的this
。正是由於它沒有this
,因此也就不能用做構造函數。
var col = 3
var obj = { col: 5, show: function () { console.log(this.col) } } obj.show() // 5
var col = 3
var obj = { col: 5, show: () => console.log(this.col) } obj.show() // 3
let col = 3 let obj = { col: 5, show: () => console.log(this.col) } obj.show() // undefined
function Person() { // 構造函數 Person() 定義的 `this` 就是新實例對象本身
this.age = 0; setInterval(function growUp() { // 在非嚴格模式下,growUp() 函數定義了其內部的 `this`爲全局對象,
// 不一樣於構造函數Person()的定義的 `this`
this.age++; }, 3000);} var p = new Person();
上面定時器的this並非指向構造函數的this,這並非咱們想要的。因此想要定時器裏面的this指向構造函數,咱們能夠經過把this的值賦值給變量,而後將該變量放到閉包中來解決。prototype
function Person() { var self = this; // 也有人選擇使用 `that` 而非 `self`, 只要保證一致就好.
self.age = 0; setInterval(function growUp() { // 回調裏面的 `self` 變量就指向了指望的那個對象了
self.age++; }, 3000);} var p = new Person();
咱們還可使用bind函數,把指望的this值傳遞給growUp函數。固然,咱們可使用箭頭函數輕鬆實現,箭頭函數會捕獲他所在的上下文的this值,做爲本身的this值。rest
function Person() { this.age = 0; setInterval(() => { // 回調裏面的 `this` 變量就指向了指望的那個對象了
this.age++; }, 3000);} var p = new Person();
call和apply調用對箭頭函數this的影響:code
var adder = { base : 1, add : function(a) { var f = v => v + this.base; return f(a); }, addThruCall: function(a) { var f = v => v + this.base; var b = { base : 2 }; return f.call(b, a); }}; console.log(adder.add(1)); // 輸出 2
console.log(adder.addThruCall(1)); // 仍然輸出 2(而不是3 ——譯者注)
分析以下:對象
一、adder.add(1)執行add函數,add返回f(a)也就是f(1)的調用,執行f()函數,f是箭頭函數寫法,this.base中的this指向對象自己,因此輸出2blog
二、adder.addThruCall(1)執行addThruCall,返回f.call(b, a),call本質是將f的this指向b,因此此時的this.base理應是2,可是由於是箭頭函數的寫法,this已經在詞法層面完成了綁定,經過call或者apply方法調用的時候,只是出入了參數,並無改變this的指向,因此此時的值仍是2.
3、arguments
箭頭函數不會在其內部暴露出參數,也就是說沒有本身的arguments:
var arguments = 42;var arr = () => arguments; arr(); // 42
function foo() { var f = (i) => arguments[0]+i; // foo函數的間接參數綁定
return f(2);} foo(1); // 3
不過在大多數情形下,rest參數能夠給出一個解決方案:
function foo() { var f = (...args) => args[0]; return f(2); } foo(1); // 2
4、注意事項
一、箭頭函數不能用做構造器,和new一塊兒用就會報錯
var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor
二、箭頭函數沒有原型屬性
var Foo = () => {}; console.log(Foo.prototype); // undefined
三、箭頭函數既支持簡寫也支持常規編寫
var func = x => x * x; // 簡寫函數 省略return
var func = (x, y) => { return x + y; }; //常規編寫 明確的返回值