首頁  >  文章  >  web前端  >  箭頭函數和普通函數區別

箭頭函數和普通函數區別

hzc
hzc轉載
2020-06-12 10:38:163766瀏覽

前言


箭頭函數是前端面試環節的一個高頻考點,箭頭函數是ES6的API,相信很多人都知道,因為它的語法比一般的函數更簡潔,所以深受大家的喜愛。這是我們在日常開發中一直使用的API,但大多數同學對它的理解還不夠,下面我們來詳細了解下箭頭函數的基本語法,以及箭頭函數與普通函數的區別。

一、基本語法

【1.1】定義函數

定義箭頭函在數字語法上要比普通函數簡潔得多,ES6中允許使用箭頭

=>

來定義箭頭函數,箭頭函數省去了function 關鍵字,函數的參數放在=>前面的括號中,函數體跟在=>後的花括號中。

// 箭头函数
let fun = (name) => {
    return `Hello ${name} !`;
};

// 普通函数
let fun = function (name) {
    return `Hello ${name} !`;
};

【1.2】箭頭函數的參數

① 如果箭頭函數沒有參數,直接寫一個空括號即可。

② 如果箭頭函數的參數只有一個,也可以省去包裹參數的括號。

③ 如果箭頭函數有多個參數,將參數依序用逗號(,)分隔,包裹在括號中即可。

// 没有参数
let fun1 = () => {
    console.log('dingFY');
};

// 只有一个参数,可以省去参数括号
let fun2 = name => {
    console.log(`Hello ${name} !`)
};

// 有多个参数,逗号分隔
let fun3 = (val1, val2, val3) => {
    return [val1, val2, val3];
};

【1.3】箭頭函數的函數體

① 如果箭頭函數的函數體只有一句程式碼,就是簡單回傳某個變數或回傳一個簡單的JS表達式,可以省去函數體的大括號{ }。

let fun = val => val;
// 等同于
let fun = function (val) { return val };

let sum = (num1, num2) => num1 + num2;
// 等同于
let sum = function(num1, num2) {
  return num1 + num2;
};

② 如果箭頭函數的函數體只有一句代碼,就是返回一個對象,可以像下面這樣寫:

// 用小括号包裹要返回的对象,不报错
let getTempItem = id => ({ id: id, name: "Temp" });

// 但绝不能这样写,会报错,因为对象的大括号会被解释为函数体的大括号
let getTempItem = id => { id: id, name: "Temp" };

③ 如果箭頭函數的函數體只有一條語句並且不需要返回值(最常見是呼叫一個函數),可以在這條語句前面加上void關鍵字

let fun = () => void doesNotReturn();

二、箭頭函數與普通函數的差異


【2.1】語法更簡潔、清晰

從上面的箭頭函數基本語法範例可以看出,箭頭函數的定義要比一般函數定義簡潔、清晰得多,很快捷。

【2.2】箭頭函數沒有prototype (原型),所以箭頭函數本身沒有this

// 箭头函数
let a = () => {};
console.log(a.prototype); // undefined

// 普通函数
function a() {};
console.log(a.prototype); // {constructor:f}

【2.3】箭頭函數不會創建自己的this

箭頭函數沒有自己的this,箭頭函數的this指向在定義(注意:是定義時,不是呼叫時)的時候繼承自外層第一個普通函數的this。所以,箭頭函數中 this 的指向在它被定義的時候就已經確定了,之後永遠不會改變。

let obj = {
  a: 10,
  b: () => {
    console.log(this.a); // undefined
    console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  },
  c: function() {
    console.log(this.a); // 10
    console.log(this); // {a: 10, b: ƒ, c: ƒ}
  }
}
obj.b(); 
obj.c();

【2.4】call | apply | bind 無法改變箭頭函數中this的指向

call | apply | bind方法可以用來動態修改函數執行時this的指向,但由於箭頭函數的this定義時就已經確定且永遠不會改變。所以使用這些方法永遠也改變不了箭頭函數this的指向。

var id = 10;
let fun = () => {
    console.log(this.id)
};
fun();     // 10
fun.call({ id: 20 });     // 10
fun.apply({ id: 20 });    // 10
fun.bind({ id: 20 })();   // 10

【2.4】call | apply | bind 無法改變箭頭函數中this的指向

call | apply | bind方法可以用來動態修改函數執行時this的指向,但由於箭頭函數的this定義時就已經確定且永遠不會改變。所以使用這些方法永遠也改變不了箭頭函數this的指向。

var id = 10;
let fun = () => {
    console.log(this.id)
};
fun();     // 10
fun.call({ id: 20 });     // 10
fun.apply({ id: 20 });    // 10
fun.bind({ id: 20 })();   // 10

【2.5】箭頭函數不能作為建構子使用

我們先了解建構子的new都做了些什麼?簡單來說,分為四個步驟: ① JS 內部首先會先生成一個物件; ② 再把函數中的this指向該物件; ③ 然後執行建構子中的語句; ④ 最終傳回該物件實例。

但是! !因為箭頭函數沒有自己的this,它的this其實是繼承了外層執行環境中的this,而this指向永遠不會隨在哪裡調用、被誰調用而改變,所以箭頭函數不能作為構造函數使用,或者說構造函數不能定義成箭頭函數,否則用new呼叫時會報錯!

let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};

// 报错
let p = new Fun('dingFY', 24);

【2.6】箭頭函數不綁定arguments,取代用rest參數...取代arguments對象,來存取箭頭函數的參數列表

箭頭函數沒有自己的arguments物件。在箭頭函數中存取arguments實際上獲得的是外層局部(函數)執行環境中的值。

// 普通函数
function A(a){
  console.log(arguments);
}
A(1,2,3,4,5,8);  //  [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]

// 箭头函数
let B = (b)=>{
  console.log(arguments);
}
B(2,92,32,32);   // Uncaught ReferenceError: arguments is not defined

// rest参数...
let C = (...c) => {
  console.log(c);
}
C(3,82,32,11323);  // [3, 82, 32, 11323]

【2.7】箭頭函數不能用作Generator函數,不能使用yield關鍵字

推薦教學:《JS教學

以上是箭頭函數和普通函數區別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除