箭頭函數

先來看一段代碼:閉包

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
 
分析:
     調用者是obj,因此this指向obj
 
var col = 3
var obj = { col: 5, show: () => console.log(this.col) } obj.show() // 3
 
分析:
     由於是箭頭函數,var定義的obj,做用域在全局,因此此時的this指向window
 
let col = 3 let obj = { col: 5, show: () => console.log(this.col) } obj.show() // undefined
 
分析:
     由於是let聲明,let、const、class命令聲明的全局變量是不屬於頂層對象的屬性的,因此,this就既不指向window,也不指向obj

 

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; }; //常規編寫 明確的返回值
相關文章
相關標籤/搜索