一文詳解JavaScript普通函數(shù)與箭頭函數(shù)的本質(zhì)區(qū)別與使用場(chǎng)景
從一段代碼說(shuō)起
先來(lái)看一個(gè)日常開(kāi)發(fā)中常見(jiàn)的場(chǎng)景:
// 普通函數(shù)
function greet(name) {
return `Hello, ${name}!`;
}
// 箭頭函數(shù)
const greetArrow = name => `Hello, ${name}!`;
看起來(lái)箭頭函數(shù)更簡(jiǎn)潔,但它們的區(qū)別遠(yuǎn)不止語(yǔ)法上的簡(jiǎn)化。讓我們深入探究它們的本質(zhì)差異。
核心區(qū)別一覽
1. this綁定機(jī)制(最重要的區(qū)別?。?/h3>
普通函數(shù)的this是動(dòng)態(tài)綁定的,取決于函數(shù)被調(diào)用的方式:
const person = {
name: '我',
sayName: function() {
console.log(this.name); // 正確指向person對(duì)象
}
};
person.sayName(); // 輸出"我"
箭頭函數(shù)的this是詞法作用域綁定,繼承自外層作用域:
const person = {
name: '我',
sayName: () => {
console.log(this.name); // 指向window/undefined(嚴(yán)格模式)
}
};
person.sayName(); // 輸出undefined
這個(gè)特性讓箭頭函數(shù)特別適合用在回調(diào)函數(shù)中:
// 使用普通函數(shù)需要額外綁定this
const obj = {
values: [1, 2, 3],
printValues: function() {
this.values.forEach(function(item) {
console.log(item, this); // 這里的this不是obj了!
}.bind(this));
}
};
// 使用箭頭函數(shù)則自動(dòng)綁定
const objArrow = {
values: [1, 2, 3],
printValues: function() {
this.values.forEach(item => {
console.log(item, this); // 正確指向objArrow
});
}
};
2. 構(gòu)造函數(shù)能力
普通函數(shù)可以作為構(gòu)造函數(shù)使用:
function Person(name) {
this.name = name;
}
const me = new Person('我');
console.log(me.name); // "我"
箭頭函數(shù)不能作為構(gòu)造函數(shù):
const PersonArrow = (name) => {
this.name = name; // 報(bào)錯(cuò)!
};
// const me = new PersonArrow('我'); // TypeError
3. arguments對(duì)象
普通函數(shù)可以訪問(wèn)arguments對(duì)象:
function sum() {
let total = 0;
for(let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(1, 2, 3)); // 6
箭頭函數(shù)沒(méi)有自己的arguments對(duì)象:
const sumArrow = () => {
console.log(arguments); // 報(bào)錯(cuò)!
};
// sumArrow(1, 2, 3); // ReferenceError
不過(guò),箭頭函數(shù)可以使用剩余參數(shù)語(yǔ)法:
const sumArrow = (...args) => {
return args.reduce((a, b) => a + b, 0);
};
console.log(sumArrow(1, 2, 3)); // 6
4. 原型屬性
普通函數(shù)有prototype屬性:
function Foo() {}
console.log(Foo.prototype); // 存在
箭頭函數(shù)沒(méi)有prototype屬性:
const Bar = () => {};
console.log(Bar.prototype); // undefined
語(yǔ)法差異
除了功能上的區(qū)別,語(yǔ)法上也有明顯不同:
// 普通函數(shù)
function add(a, b) {
return a + b;
}
// 箭頭函數(shù)多種寫(xiě)法
const addArrow1 = (a, b) => {
return a + b;
};
// 單行簡(jiǎn)寫(xiě)
const addArrow2 = (a, b) => a + b;
// 單個(gè)參數(shù)可省略括號(hào)
const square = x => x * x;
// 無(wú)參數(shù)需要括號(hào)
const sayHi = () => console.log('Hi!');
使用場(chǎng)景建議
根據(jù)我的開(kāi)發(fā)經(jīng)驗(yàn),以下是一些最佳實(shí)踐:
使用箭頭函數(shù)的場(chǎng)景:
- 回調(diào)函數(shù)(尤其是需要保持this一致的場(chǎng)景)
- 簡(jiǎn)單的單行函數(shù)
- 函數(shù)式編程(map/filter/reduce等)
- 需要詞法作用域綁定的情況
使用普通函數(shù)的場(chǎng)景:
- 需要作為構(gòu)造函數(shù)
- 需要訪問(wèn)arguments對(duì)象
- 對(duì)象方法(除非明確需要詞法作用域)
- 需要函數(shù)提升的場(chǎng)景
- 需要?jiǎng)討B(tài)this的場(chǎng)景(如事件處理函數(shù))
實(shí)際案例對(duì)比
讓我們看一個(gè)更復(fù)雜的實(shí)際案例:
// 使用普通函數(shù)
function Timer() {
this.seconds = 0;
setInterval(function() {
this.seconds++; // 這里的this指向window!
console.log(this.seconds);
}, 1000);
}
// const timer = new Timer(); // 不會(huì)按預(yù)期工作
// 修復(fù)方案1:保存this引用
function TimerFixed1() {
this.seconds = 0;
const self = this;
setInterval(function() {
self.seconds++;
console.log(self.seconds);
}, 1000);
}
// 修復(fù)方案2:使用bind
function TimerFixed2() {
this.seconds = 0;
setInterval(function() {
this.seconds++;
console.log(this.seconds);
}.bind(this), 1000);
}
// 最佳方案:使用箭頭函數(shù)
function TimerArrow() {
this.seconds = 0;
setInterval(() => {
this.seconds++; // 正確綁定到TimerArrow實(shí)例
console.log(this.seconds);
}, 1000);
}
性能考量
雖然現(xiàn)代JavaScript引擎已經(jīng)對(duì)兩種函數(shù)都做了很好的優(yōu)化,但在極端性能敏感的場(chǎng)景下:
- 普通函數(shù)在作為構(gòu)造函數(shù)時(shí)性能更好
- 箭頭函數(shù)在作為回調(diào)時(shí)可能更高效(因?yàn)椴恍枰幚韙his綁定)
不過(guò),在大多數(shù)應(yīng)用中,這種性能差異可以忽略不計(jì),應(yīng)該以代碼清晰度和維護(hù)性為首要考慮。
常見(jiàn)誤區(qū)
- 在對(duì)象方法中使用箭頭函數(shù):
const counter = {
count: 0,
increment: () => {
this.count++; // 錯(cuò)誤!this指向外層作用域
}
};
- 在原型方法中使用箭頭函數(shù):
function Person(name) {
this.name = name;
}
// 錯(cuò)誤用法
Person.prototype.sayName = () => {
console.log(this.name); // 不會(huì)按預(yù)期工作
};
- 在需要?jiǎng)討B(tài)this的事件處理中使用箭頭函數(shù):
button.addEventListener('click', () => {
console.log(this); // 指向外層作用域,不是button元素
});
// 應(yīng)該使用普通函數(shù)
button.addEventListener('click', function() {
console.log(this); // 指向button元素
});
總結(jié)
普通函數(shù)和箭頭函數(shù)各有千秋,理解它們的核心區(qū)別對(duì)于寫(xiě)出高質(zhì)量的JavaScript代碼至關(guān)重要:
- this綁定:箭頭函數(shù)繼承外層this,普通函數(shù)動(dòng)態(tài)綁定
- 構(gòu)造函數(shù):只有普通函數(shù)能作為構(gòu)造函數(shù)
- arguments:箭頭函數(shù)沒(méi)有自己的arguments對(duì)象
- 語(yǔ)法:箭頭函數(shù)更簡(jiǎn)潔,特別適合單行函數(shù)
- 使用場(chǎng)景:根據(jù)需求選擇合適的函數(shù)類型
記?。簺](méi)有絕對(duì)的好壞,只有適合不適合。在實(shí)際開(kāi)發(fā)中,我通常會(huì)根據(jù)具體場(chǎng)景靈活選擇,有時(shí)甚至?xí)旌鲜褂盟鼈儊?lái)發(fā)揮各自的優(yōu)勢(shì)。
以上就是一文詳解JavaScript普通函數(shù)與箭頭函數(shù)的本質(zhì)區(qū)別與使用場(chǎng)景的詳細(xì)內(nèi)容,更多關(guān)于JavaScript普通函數(shù)與箭頭函數(shù)區(qū)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript中Array的filter函數(shù)詳解
這篇文章主要介紹了JavaScript中Array的filter函數(shù)詳解,filter?為數(shù)組中的每個(gè)元素調(diào)用一次callback函數(shù),W更多具體內(nèi)容,需要的朋友可以參考一下2022-07-07
JavaScript實(shí)現(xiàn)抽獎(jiǎng)器效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)抽獎(jiǎng)器效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
借助云開(kāi)發(fā)實(shí)現(xiàn)小程序短信驗(yàn)證碼的發(fā)送
這篇文章主要介紹了借助云開(kāi)發(fā)實(shí)現(xiàn)小程序短信驗(yàn)證碼的發(fā)送,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
uniapp封裝axios的詳細(xì)過(guò)程(大可不必那么麻煩)
在uniapp中使用axios進(jìn)行請(qǐng)求時(shí),uniapp無(wú)法使用axios的適配器,下面這篇文章主要給大家介紹了關(guān)于uniapp封裝axios的詳細(xì)過(guò)程,需要的朋友可以參考下2022-10-10
如何清除IE10+ input X 文本框的叉叉和密碼輸入框的眼睛圖標(biāo)
從IE 10開(kāi)始,type=”text” 的 input 在用戶輸入內(nèi)容后,會(huì)自動(dòng)產(chǎn)生一個(gè)小叉叉(X),方便用戶點(diǎn)擊清除已經(jīng)輸入的文本,下面通過(guò)本文給大家介紹下如何清除IE10+ input X 文本框的叉叉和密碼輸入框的眼睛圖標(biāo)2016-12-12
JavaScript設(shè)計(jì)模式之代理模式介紹
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之代理模式介紹,代理模式顧名思義就是用一個(gè)類來(lái)代替另一個(gè)類來(lái)執(zhí)行方法功能,需要的朋友可以參考下2014-12-12
Javascript attachEvent傳遞參數(shù)的辦法
找了半天找到的解決辦法,看介紹說(shuō)是javascript的閉包問(wèn)題,導(dǎo)致得不能直接讀取外部的那個(gè)函數(shù),不然就所有傳遞的參數(shù)都變?yōu)樽詈笠粋€(gè)了。2009-12-12
快速查找數(shù)組中的某個(gè)元素并返回下標(biāo)示例
最近在寫(xiě)jquery的combobox插件時(shí)遇到效率問(wèn)題,再加上jquery選擇器的類帥選,導(dǎo)致效率很慢,采用以下方式二,可以輕松解決此問(wèn)題2013-09-09

