溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

es6中箭頭函數(shù)和普通函數(shù)的區(qū)別有哪些

發(fā)布時(shí)間:2022-03-08 13:38:59 來(lái)源:億速云 閱讀:149 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要介紹es6中箭頭函數(shù)和普通函數(shù)的區(qū)別有哪些,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

區(qū)別:1、箭頭函數(shù)的定義要比普通函數(shù)定義簡(jiǎn)潔、清晰得多,很快捷;2、箭頭函數(shù)不會(huì)創(chuàng)建自己的this,而普通函數(shù)會(huì);3、箭頭函數(shù)不能作為構(gòu)造函數(shù)使用,而箭頭函數(shù)能作為構(gòu)造函數(shù)使用;4、箭頭函數(shù)沒(méi)有自己的arguments,而箭頭函數(shù)有。

本教程操作環(huán)境:windows7系統(tǒng)、ECMAScript 6版、Dell G3電腦。

箭頭函數(shù)是前端面試環(huán)節(jié)的一個(gè)高頻考點(diǎn),箭頭函數(shù)是ES6的API,相信很多人都知道,因?yàn)樗恼Z(yǔ)法比一般的函數(shù)更簡(jiǎn)潔,所以深受大家的喜愛(ài)。

一、基本語(yǔ)法

ES6中允許使用箭頭=>來(lái)定義箭頭函數(shù),具體語(yǔ)法,我們來(lái)看一個(gè)簡(jiǎn)單的例子:

// 箭頭函數(shù)
let fun = (name) => {
    // 函數(shù)體
    return `Hello ${name} !`;
};

// 等同于
let fun = function (name) {
    // 函數(shù)體
    return `Hello ${name} !`;
};

可以看出,定義箭頭函在數(shù)語(yǔ)法上要比普通函數(shù)簡(jiǎn)潔得多。箭頭函數(shù)省去了function關(guān)鍵字,采用箭頭=>來(lái)定義函數(shù)。函數(shù)的參數(shù)放在=>前面的括號(hào)中,函數(shù)體跟在=>后的花括號(hào)中。

關(guān)于箭頭函數(shù)的參數(shù):

如果箭頭函數(shù)沒(méi)有參數(shù),直接寫(xiě)一個(gè)空括號(hào)即可。

如果箭頭函數(shù)的參數(shù)只有一個(gè),也可以省去包裹參數(shù)的括號(hào)。

如果箭頭函數(shù)有多個(gè)參數(shù),將參數(shù)依次用逗號(hào)(,)分隔,包裹在括號(hào)中即可。

// 沒(méi)有參數(shù)
let fun1 = () => {
    console.log(111);
};

// 只有一個(gè)參數(shù),可以省去參數(shù)括號(hào)
let fun2 = name => {
    console.log(`Hello ${name} !`)
};

// 有多個(gè)參數(shù)
let fun3 = (val1, val2, val3) => {
    return [val1, val2, val3];
};

關(guān)于箭頭函數(shù)的函數(shù)體:

如果箭頭函數(shù)的函數(shù)體只有一句代碼,就是簡(jiǎn)單返回某個(gè)變量或者返回一個(gè)簡(jiǎn)單的JS表達(dá)式,可以省去函數(shù)體的大括號(hào){ }。

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

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

如果箭頭函數(shù)的函數(shù)體只有一句代碼,就是返回一個(gè)對(duì)象,可以像下面這樣寫(xiě):

// 用小括號(hào)包裹要返回的對(duì)象,不報(bào)錯(cuò)
let getTempItem = id => ({ id: id, name: "Temp" });

// 但絕不能這樣寫(xiě),會(huì)報(bào)錯(cuò)。
// 因?yàn)閷?duì)象的大括號(hào)會(huì)被解釋為函數(shù)體的大括號(hào)
let getTempItem = id => { id: id, name: "Temp" };

如果箭頭函數(shù)的函數(shù)體只有一條語(yǔ)句并且不需要返回值(最常見(jiàn)是調(diào)用一個(gè)函數(shù)),可以給這條語(yǔ)句前面加一個(gè)void關(guān)鍵字

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

箭頭函數(shù)最常見(jiàn)的用處就是簡(jiǎn)化回調(diào)函數(shù)。

// 例子一
// 正常函數(shù)寫(xiě)法
[1,2,3].map(function (x) {
  return x * x;
});

// 箭頭函數(shù)寫(xiě)法
[1,2,3].map(x => x * x);

// 例子二
// 正常函數(shù)寫(xiě)法
var result = [2, 5, 1, 4, 3].sort(function (a, b) {
  return a - b;
});

// 箭頭函數(shù)寫(xiě)法
var result = [2, 5, 1, 4, 3].sort((a, b) => a - b);

二、箭頭函數(shù)與普通函數(shù)的區(qū)別

1、語(yǔ)法更加簡(jiǎn)潔、清晰

從上面的基本語(yǔ)法示例中可以看出,箭頭函數(shù)的定義要比普通函數(shù)定義簡(jiǎn)潔、清晰得多,很快捷。

2、箭頭函數(shù)不會(huì)創(chuàng)建自己的this(重要!!深入理解!?。?/strong>

我們先來(lái)看看MDN上對(duì)箭頭函數(shù)this的解釋。

箭頭函數(shù)不會(huì)創(chuàng)建自己的this,所以它沒(méi)有自己的this,它只會(huì)從自己的作用域鏈的上一層繼承this。

箭頭函數(shù)沒(méi)有自己的this,它會(huì)捕獲自己在定義時(shí)(注意,是定義時(shí),不是調(diào)用時(shí))所處的外層執(zhí)行環(huán)境的this,并繼承這個(gè)this值。所以,箭頭函數(shù)中this的指向在它被定義的時(shí)候就已經(jīng)確定了,之后永遠(yuǎn)不會(huì)改變。

來(lái)看個(gè)例子:

var id = 'Global';

function fun1() {
    // setTimeout中使用普通函數(shù)
    setTimeout(function(){
        console.log(this.id);
    }, 2000);
}

function fun2() {
    // setTimeout中使用箭頭函數(shù)
    setTimeout(() => {
        console.log(this.id);
    }, 2000)
}

fun1.call({id: 'Obj'});     // 'Global'

fun2.call({id: 'Obj'});     // 'Obj'

上面這個(gè)例子,函數(shù)fun1中的setTimeout中使用普通函數(shù),2秒后函數(shù)執(zhí)行時(shí),這時(shí)函數(shù)其實(shí)是在全局作用域執(zhí)行的,所以this指向Window對(duì)象,this.id就指向全局變量id,所以輸出'Global'。 但是函數(shù)fun2中的setTimeout中使用的是箭頭函數(shù),這個(gè)箭頭函數(shù)的this在定義時(shí)就確定了,它繼承了它外層fun2的執(zhí)行環(huán)境中的this,而fun2調(diào)用時(shí)thiscall方法改變到了對(duì)象{id: 'Obj'}中,所以輸出'Obj'。

再來(lái)看另一個(gè)例子:

var id = 'GLOBAL';
var obj = {
  id: 'OBJ',
  a: function(){
    console.log(this.id);
  },
  b: () => {
    console.log(this.id);
  }
};

obj.a();    // 'OBJ'
obj.b();    // 'GLOBAL'

上面這個(gè)例子,對(duì)象obj的方法a使用普通函數(shù)定義的,普通函數(shù)作為對(duì)象的方法調(diào)用時(shí),this指向它所屬的對(duì)象。所以,this.id就是obj.id,所以輸出'OBJ'。 但是方法b是使用箭頭函數(shù)定義的,箭頭函數(shù)中的this實(shí)際是繼承的它定義時(shí)所處的全局執(zhí)行環(huán)境中的this,所以指向Window對(duì)象,所以輸出'GLOBAL'。(這里要注意,定義對(duì)象的大括號(hào){}是無(wú)法形成一個(gè)單獨(dú)的執(zhí)行環(huán)境的,它依舊是處于全局執(zhí)行環(huán)境中!!

3、箭頭函數(shù)繼承而來(lái)的this指向永遠(yuǎn)不變(重要??!深入理解?。。?/strong>

上面的例子,就完全可以說(shuō)明箭頭函數(shù)繼承而來(lái)的this指向永遠(yuǎn)不變。對(duì)象obj的方法b是使用箭頭函數(shù)定義的,這個(gè)函數(shù)中的this永遠(yuǎn)指向它定義時(shí)所處的全局執(zhí)行環(huán)境中的this,即便這個(gè)函數(shù)是作為對(duì)象obj的方法調(diào)用,this依舊指向Window對(duì)象。

4、.call()/.apply()/.bind()無(wú)法改變箭頭函數(shù)中this的指向

.call()/.apply()/.bind()方法可以用來(lái)動(dòng)態(tài)修改函數(shù)執(zhí)行時(shí)this的指向,但由于箭頭函數(shù)的this定義時(shí)就已經(jīng)確定且永遠(yuǎn)不會(huì)改變。所以使用這些方法永遠(yuǎn)也改變不了箭頭函數(shù)this的指向,雖然這么做代碼不會(huì)報(bào)錯(cuò)。

var id = 'Global';
// 箭頭函數(shù)定義在全局作用域
let fun1 = () => {
    console.log(this.id)
};

fun1();     // 'Global'
// this的指向不會(huì)改變,永遠(yuǎn)指向Window對(duì)象
fun1.call({id: 'Obj'});     // 'Global'
fun1.apply({id: 'Obj'});    // 'Global'
fun1.bind({id: 'Obj'})();   // 'Global'

5、箭頭函數(shù)不能作為構(gòu)造函數(shù)使用

我們先了解一下構(gòu)造函數(shù)的new都做了些什么?簡(jiǎn)單來(lái)說(shuō),分為四步: ① JS內(nèi)部首先會(huì)先生成一個(gè)對(duì)象; ② 再把函數(shù)中的this指向該對(duì)象; ③ 然后執(zhí)行構(gòu)造函數(shù)中的語(yǔ)句; ④ 最終返回該對(duì)象實(shí)例。

但是!!因?yàn)榧^函數(shù)沒(méi)有自己的this,它的this其實(shí)是繼承了外層執(zhí)行環(huán)境中的this,且this指向永遠(yuǎn)不會(huì)隨在哪里調(diào)用、被誰(shuí)調(diào)用而改變,所以箭頭函數(shù)不能作為構(gòu)造函數(shù)使用,或者說(shuō)構(gòu)造函數(shù)不能定義成箭頭函數(shù),否則用new調(diào)用時(shí)會(huì)報(bào)錯(cuò)!

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

// 報(bào)錯(cuò)
let p = new Fun('cao', 24);

6、箭頭函數(shù)沒(méi)有自己的arguments

箭頭函數(shù)沒(méi)有自己的arguments對(duì)象。在箭頭函數(shù)中訪問(wèn)arguments實(shí)際上獲得的是外層局部(函數(shù))執(zhí)行環(huán)境中的值。

// 例子一
let fun = (val) => {
    console.log(val);   // 111
    // 下面一行會(huì)報(bào)錯(cuò)
    // Uncaught ReferenceError: arguments is not defined
    // 因?yàn)橥鈱尤汁h(huán)境沒(méi)有arguments對(duì)象
    console.log(arguments); 
};
fun(111);

// 例子二
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    // ①
    let fun = () => {
        let argIn = arguments;
        console.log(argIn);     // ②
        console.log(argOut === argIn);  // ③
    };
    fun();
}
outer(111, 222);

上面例子二,①②③處的輸出結(jié)果如下:

es6中箭頭函數(shù)和普通函數(shù)的區(qū)別有哪些

很明顯,普通函數(shù)outer內(nèi)部的箭頭函數(shù)fun中的arguments對(duì)象,其實(shí)是沿作用域鏈向上訪問(wèn)的外層outer函數(shù)的arguments對(duì)象。

可以在箭頭函數(shù)中使用rest參數(shù)代替arguments對(duì)象,來(lái)訪問(wèn)箭頭函數(shù)的參數(shù)列表?。?/strong>

7、箭頭函數(shù)沒(méi)有原型prototype

let sayHi = () => {
    console.log('Hello World !')
};
console.log(sayHi.prototype); // undefined

8、箭頭函數(shù)不能用作Generator函數(shù),不能使用yeild關(guān)鍵字

以上是“es6中箭頭函數(shù)和普通函數(shù)的區(qū)別有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

es6
AI