普通函數和箭頭函數

普通函數和箭頭函數

寫在前面

函數(Function)JavaScript 裏的‘一等公民’。是由稱爲函數體的一系列語句組成。能夠當作入參,出參(返回值)使用。和對象同樣,有本身的屬性和方法。區別之處在於能夠被調用。數據類型是 function(用 typeof 判斷),用 Object.prototype.toString.call() 判斷是 [object Function]。若是沒有使用 retrun 語句,則默認返回 undefined。反之則函數必須使用 return 語句來指定一個要返回的值。(使用 new 關鍵字調用一個構造函數除外,再也不是實例化一個對象)。函數執行時,this 關鍵字並不會指向正在運行的函數自己,而是指向調用該函數的對象。
函數表達式不會提高,所以在使用以前必須先聲明。和用 var 聲明變量不同。segmentfault

產生緣由

箭頭函數的產生緣由就是在於 this 關鍵字指向問題。它很容易讓人產生疑惑,尤爲是當函數調用層級比較多的時候。和傳統函數定義相比,語法也相對簡潔。而且沒有本身的thisargumentssupernew.target。這些函數表達式更適用於那些原本須要匿名函數的地方,而且它們不能用做構造函數。箭頭函數 this 指向的固定化,並非由於函數內部作了處理,而是由於箭頭函數在建立的時候根本就沒有本身的 thisapp

使用箭頭函數須要注意的點

1,函數體內的 this 對象,是定義時所在對象,而不是調用該函數的對象。
2,正由於本身自己沒有 this 對象,所以不能夠用做構造函數,不能用 call()apply()bind()這些方法去改變 this 的指向。
3,不綁定 arguments 對象,能夠使用 rest 參數來解決。
4,嚴格模式(use strict)中,指定的與 this 相關的規則都將被忽略。dom

var aaa = () => {
    'use strict';
    console.log(this);
    // window
}

var bbb = function() {
    'use strict';
    console.log(this);
    // undefined
}

5,不能使用 new 操做符,不然會報錯函數

var Func = () => {};
var func = new Func();
// TypeError: Func is not a constructor

6,沒有 prototype 屬性this

var Func = () => {};
console.log(Func.prototype);
// undefined

7,不能用做生成器。 yield 關鍵字一般不能在箭頭函數中使用(除非是嵌套在容許使用的函數內)。
8,箭頭函數的簡寫,能夠直接省略 return,在塊體中,必須使用明確的 return 語句。若是須要返回對象字面量的話,記得用圓括號包起來。prototype

var func = () => ({num: 1});

寫在後面

拋一個大佬留下的問題,有箭頭函數的 IIEF:翻譯

(() => {
console.log('執行看看');
// 執行看看
})();

這個是能夠的,可是下面的寫法就會報錯rest

(() => {
console.log('執行看看');
// Uncaught SyntaxError: Unexpected token (
}());

有知道緣由的小夥伴嗎?code


2018-07-18
補充一下幾點:
1,在對象字面量上定義方法,會出現問題
以下代碼執行:對象

var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  },
  d() {
    console.log( this.i, this)  
  }
}
obj.b(); 
// undefined Window
obj.c();
// 10 obj對象
obj.d(); 
// 10 obj對象

obj.b 使用箭頭函數來定義,可是調用 obj.b() 時出現了異常。由於當執行b的時候上下文仍然是window,這是由於箭頭函數已經綁定了window作爲上下文。
解決辦法就是不要在對象的方法上使用箭頭函數短語法,這樣this關鍵字會在調用時決定,而不是早早綁定在閉合的上下文中。如 obj.d()

一樣的規則也適用於給對象 prototype原型上定義方法,如

function Obj(name) {
  this.objName = name;  
}
Obj.prototype.getObjName = () => {
    console.log(this === window);
    // true
    return this.objName;
}

var obj = new Obj('小紅');
obj.getObjName(); 
// undefined

2,動態上下文中的回調函數
this是js中很是強大的特色,他讓函數能夠根據其調用方式動態的改變上下文,而後箭頭函數直接在聲明時就綁定了this對象,因此再也不是動態的。

在客戶端,在dom元素上綁定事件監聽函數是很是廣泛的行爲,在dom事件被觸發時,回調函數中的this指向該dom,可當咱們使用箭頭函數時:

button.addEventListener('click', () => {  
    console.log(this === window); // => true
    this.innerHTML = 'Clicked button';
});

由於這個回調的箭頭函數是在全局上下文中被定義的,因此他的this是window。因此當this是由目標對象決定時,咱們應該使用函數表達式:

button.addEventListener('click', function() {  
    console.log(this === button); // => true
    this.innerHTML = 'Clicked button';
});

以上補充的摘自:翻譯 | ES6 箭頭函數使用禁忌

相關文章
相關標籤/搜索