JavaScript 普通函數(shù)與箭頭函數(shù)的區(qū)別小結(jié)
在前端面試中,“箭頭函數(shù)與普通函數(shù)的區(qū)別”是一道出現(xiàn)頻率極高的基礎(chǔ)題。然而,很多開發(fā)者僅停留在“寫法更簡(jiǎn)單”或“this 指向不同”的淺層認(rèn)知上。作為一名合格的前端工程師,我們需要從 JavaScript 引擎的執(zhí)行機(jī)制層面,深入理解這兩者的本質(zhì)差異。
本文將從語法特性、運(yùn)行原理、核心差異及面試實(shí)戰(zhàn)四個(gè)維度,對(duì)這一知識(shí)點(diǎn)進(jìn)行全方位的拆解。
第一部分:直觀的代碼對(duì)比(語法層)
首先,我們通過代碼直觀地感受兩者在書寫層面上的差異。箭頭函數(shù)(Arrow Function)本質(zhì)上是 ES6 引入的一種語法糖,旨在簡(jiǎn)化函數(shù)定義。
1. 基礎(chǔ)寫法對(duì)比
// 普通函數(shù)聲明
function add(a, b) {
return a + b;
}
// 普通函數(shù)表達(dá)式
const sub = function(a, b) {
return a - b;
};
// 箭頭函數(shù)
const mul = (a, b) => {
return a * b;
};
2. 箭頭函數(shù)的語法糖特性
箭頭函數(shù)支持高度簡(jiǎn)化的寫法,但同時(shí)也引入了一些特定的語法規(guī)則:
- 省略參數(shù)括號(hào):當(dāng)且僅當(dāng)只有一個(gè)參數(shù)時(shí),可以省略括號(hào)。
- 隱式返回:當(dāng)函數(shù)體只有一行語句時(shí),可以省略花括號(hào) {} 和 return 關(guān)鍵字。
// 省略參數(shù)括號(hào)
const square = x => x * x;
// 完整寫法對(duì)比
const squareFull = (x) => {
return x * x;
};
3. 返回對(duì)象字面量的陷阱
這是初學(xué)者最容易踩的坑。當(dāng)隱式返回一個(gè)對(duì)象字面量時(shí),必須使用小括號(hào) () 包裹,否則 JS 引擎會(huì)將對(duì)象的花括號(hào) {} 解析為函數(shù)體的代碼塊。
// 錯(cuò)誤寫法:返回 undefined,引擎認(rèn)為 {} 是代碼塊
const getUserError = id => { id: id, name: 'User' };
// 正確寫法:使用 () 包裹
const getUser = id => ({ id: id, name: 'User' });
第二部分:特性分析(原理層)
在深入差異之前,我們需要界定兩種函數(shù)的底層特性,這是理解它們行為差異的基石。
普通函數(shù)(Regular Function)
- 動(dòng)態(tài)作用域機(jī)制:this 的指向在函數(shù)被調(diào)用時(shí)決定,而非定義時(shí)。
- 完整性:擁有 prototype 屬性,可以作為構(gòu)造函數(shù)。
- 參數(shù)集合:函數(shù)體內(nèi)自動(dòng)生成 arguments 類數(shù)組對(duì)象。
- 構(gòu)造能力:具備 [[Construct]] 內(nèi)部方法和 [[Call]] 內(nèi)部方法。
箭頭函數(shù)(Arrow Function)
- 詞法作用域機(jī)制:this 的指向在函數(shù)定義時(shí)決定,捕獲外層上下文。
- 輕量化:設(shè)計(jì)之初就是為了更輕量級(jí)的執(zhí)行。沒有 prototype 屬性,沒有 arguments 對(duì)象。
- 非構(gòu)造器:只有 [[Call]] 內(nèi)部方法,沒有 [[Construct]] 內(nèi)部方法,因此不可實(shí)例化。
第三部分:核心差異深度解析
接下來,我們將從底層機(jī)制出發(fā),分點(diǎn)剖析兩者的核心差異。
1. this 指向機(jī)制(核心差異)
這是兩者最根本的區(qū)別。
普通函數(shù):this 指向取決于調(diào)用位置。
- 默認(rèn)綁定:獨(dú)立調(diào)用指向 window(嚴(yán)格模式下為 undefined)。
- 隱式綁定:作為對(duì)象方法調(diào)用,指向該對(duì)象。
- 顯式綁定:通過 call、apply、bind 修改指向。
箭頭函數(shù):this 遵循詞法作用域。它沒有自己的 this,而是捕獲定義時(shí)所在外層上下文的 this。一旦綁定,無法被修改。
場(chǎng)景演示:setTimeout 中的回調(diào)
const obj = {
name: 'Juejin',
// 普通函數(shù)
sayWithRegular: function() {
setTimeout(function() {
console.log('Regular:', this.name);
}, 100);
},
// 箭頭函數(shù)
sayWithArrow: function() {
setTimeout(() => {
console.log('Arrow:', this.name);
}, 100);
}
};
obj.sayWithRegular(); // 輸出: Regular: undefined (或 window.name)
obj.sayWithArrow(); // 輸出: Arrow: Juejin
解析:
- sayWithRegular 中的回調(diào)函數(shù)是獨(dú)立調(diào)用的,this 指向全局對(duì)象(瀏覽器中為 window),通常沒有 name 屬性。
- sayWithArrow 中的箭頭函數(shù)在定義時(shí),捕獲了外層 sayWithArrow 函數(shù)的 this(即 obj),因此能正確訪問 name。即便 setTimeout 是在全局環(huán)境中執(zhí)行回調(diào),箭頭函數(shù)的 this 依然保持不變。
顯式綁定無效驗(yàn)證:
const arrow = () => console.log(this);
const obj = { id: 1 };
// 嘗試修改箭頭函數(shù)的 this
arrow.call(obj); // 依然輸出 window/global
2. 構(gòu)造函數(shù)能力
由于箭頭函數(shù)內(nèi)部缺失 [[Construct]] 方法和 prototype 屬性,它不能被用作構(gòu)造函數(shù)。
const RegularFunc = function() {};
const ArrowFunc = () => {};
console.log(RegularFunc.prototype); // { constructor: ... }
console.log(ArrowFunc.prototype); // undefined
new RegularFunc(); // 正常執(zhí)行
new ArrowFunc(); // Uncaught TypeError: ArrowFunc is not a constructor
這一特性說明箭頭函數(shù)旨在處理邏輯運(yùn)算和回調(diào),而非對(duì)象建模。
3. 參數(shù)處理(arguments vs Rest)
在普通函數(shù)中,我們習(xí)慣使用 arguments 對(duì)象來獲取不定參數(shù)。但在箭頭函數(shù)中,訪問 arguments 會(huì)導(dǎo)致引用錯(cuò)誤(ReferenceError),因?yàn)樗静淮嬖凇?/p>
正確方案:ES6 推薦使用 剩余參數(shù)(Rest Parameters) 。
// 普通函數(shù)
function sumRegular() {
return Array.from(arguments).reduce((a, b) => a + b);
}
// 箭頭函數(shù):使用 ...args
const sumArrow = (...args) => {
// console.log(arguments); // 報(bào)錯(cuò):arguments is not defined
return args.reduce((a, b) => a + b);
};
console.log(sumArrow(1, 2, 3)); // 6
4. 方法定義中的陷阱
鑒于箭頭函數(shù)的 this 綁定機(jī)制,不推薦在定義對(duì)象原型方法或?qū)ο笞置媪糠椒〞r(shí)使用箭頭函數(shù)。
const person = {
name: 'Developer',
// 錯(cuò)誤示范:this 指向 window,而非 person 對(duì)象
sayHi: () => {
console.log(this.name);
},
// 正確示范:this 動(dòng)態(tài)綁定到調(diào)用者 person
sayHello: function() {
console.log(this.name);
}
};
person.sayHi(); // undefined
person.sayHello(); // Developer
第四部分:面試場(chǎng)景復(fù)盤(實(shí)戰(zhàn))
面試官提問:“請(qǐng)你談?wù)劶^函數(shù)和普通函數(shù)的區(qū)別。”
高分回答范本:
(建議采用“總-分-總”策略,邏輯清晰,覆蓋全面)
1. 核心總結(jié)
“箭頭函數(shù)是 ES6 引入的特性,它不僅提供了更簡(jiǎn)潔的語法,更重要的是徹底改變了 this 的綁定機(jī)制。簡(jiǎn)單來說,普通函數(shù)是動(dòng)態(tài)綁定,箭頭函數(shù)是詞法綁定。”
2. 核心差異展開
- 關(guān)于 this 指向(最重要) :
普通函數(shù)的 this 取決于調(diào)用方式,誰調(diào)用指向誰,可以通過 call/apply/bind 改變。
而箭頭函數(shù)沒有自己的 this,它會(huì)捕獲定義時(shí)上下文的 this,且永久綁定,即使使用 call 或 apply 也無法改變指向。這很好地解決了回調(diào)函數(shù)中 this 丟失的問題。 - 關(guān)于構(gòu)造能力:
箭頭函數(shù)不能作為構(gòu)造函數(shù)使用,不能使用 new 關(guān)鍵字,因?yàn)樗鼪]有 [[Construct]] 內(nèi)部方法,也沒有 prototype 原型對(duì)象。 - 關(guān)于參數(shù)處理:
箭頭函數(shù)內(nèi)部沒有 arguments 對(duì)象,如果需要獲取不定參數(shù),必須使用 ES6 的剩余參數(shù) ...args。
3. 補(bǔ)充亮點(diǎn)與使用建議
“在實(shí)際開發(fā)中,箭頭函數(shù)非常適合用在回調(diào)函數(shù)、數(shù)組方法(如 map、reduce)或者需要鎖定 this 的場(chǎng)景(如 React 組件方法)。但在定義對(duì)象方法、原型方法或動(dòng)態(tài)上下文場(chǎng)景中,為了保證 this 指向調(diào)用者,依然應(yīng)該使用普通函數(shù)。”
到此這篇關(guān)于JavaScript 普通函數(shù)與箭頭函數(shù)的區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)JavaScript 普通函數(shù)與箭頭函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文徹底講通JavaScript普通函數(shù)與箭頭函數(shù)的區(qū)別
- 深度解析JavaScript箭頭函數(shù)與普通函數(shù)兩種工作方式
- 一文詳解JavaScript普通函數(shù)與箭頭函數(shù)的本質(zhì)區(qū)別與使用場(chǎng)景
- 一篇文章詳細(xì)講解JavaScript中的this(普通函數(shù)、箭頭函數(shù)、?函數(shù)運(yùn)用)
- JavaScript箭頭函數(shù)與普通函數(shù)的區(qū)別示例詳解
- JS函數(shù)(普通函數(shù),箭頭函數(shù))中this的指向問題詳解
- JavaScript 箭頭函數(shù)的特點(diǎn)、與普通函數(shù)的區(qū)別
- JavaScript中箭頭函數(shù)與普通函數(shù)的區(qū)別詳解
- JavaScript中的普通函數(shù)和箭頭函數(shù)的區(qū)別和用法詳解
相關(guān)文章
小程序scroll-view安卓機(jī)隱藏橫向滾動(dòng)條的實(shí)現(xiàn)詳解
這篇文章主要介紹了小程序scroll-view安卓機(jī)隱藏橫向滾動(dòng)條的實(shí)現(xiàn)詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05
淺析在javascript中創(chuàng)建對(duì)象的各種模式
下面小編就為大家?guī)硪黄獪\析在javascript中創(chuàng)建對(duì)象的各種模式。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05
JavaScript知識(shí)點(diǎn)總結(jié)(五)之Javascript中兩個(gè)等于號(hào)(==)和三個(gè)等于號(hào)(===)的區(qū)別
這篇文章主要介紹了JavaScript知識(shí)點(diǎn)總結(jié)(五)之Javascript中兩個(gè)等于號(hào)(==)和三個(gè)等于號(hào)(===)的區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-05-05
JavaScript中不同標(biāo)簽頁間通信的常見方式小結(jié)
在瀏覽器中,不同標(biāo)簽頁之間進(jìn)行通信是一個(gè)常見的需求,本文介紹了JavaScript中不同標(biāo)簽頁間通信的常見方式,包括BroadcastChannel、localStorage、SharedWorker和window.postMessage+iframe,并詳細(xì)介紹了每種方法的實(shí)現(xiàn)和適用場(chǎng)景,需要的朋友可以參考下2025-05-05
Javascript表單驗(yàn)證要注意的事項(xiàng)
JavaScript 可用來在數(shù)據(jù)被送往服務(wù)器前對(duì) HTML 表單中的這些輸入數(shù)據(jù)進(jìn)行驗(yàn)證。被 JavaScript 驗(yàn)證的這些典型的表單數(shù)據(jù)有:用戶是否已填寫表單中的必填項(xiàng)目?用戶輸入的郵件地址是否合法?用戶是否已輸入合法的日期?用戶是否在數(shù)據(jù)域 (numeric field) 中輸入了文本?2014-09-09
JS實(shí)現(xiàn)的相冊(cè)圖片左右滾動(dòng)完整實(shí)例
這篇文章主要介紹了JS實(shí)現(xiàn)的相冊(cè)圖片左右滾動(dòng)效果,結(jié)合完整實(shí)例形式分析了javascript事件觸發(fā)與頁面元素屬性動(dòng)態(tài)變換的相關(guān)操作技巧,需要的朋友可以參考下2016-11-11

