箭头函数和普通函数有什么区别

箭头函数 vs 普通函数:JavaScript 核心差异全解析(含实战场景)

箭头函数是 ES6 引入的 JavaScript 语法糖,核心价值是简化代码并解决传统普通函数的this绑定痛点。二者在语法结构、this指向、功能特性和使用场景上存在本质区别,本文将从基础到进阶,结合实例全方位拆解差异,帮你精准掌握两种函数的选型逻辑。

一、语法差异:从冗余到精简的优化

语法设计是二者最直观的区别,箭头函数通过省略不必要的关键字,让代码更简洁聚焦。

普通函数:完整声明,兼容性强

普通函数支持两种定义方式,语法结构固定,需明确使用function关键字:

  • 函数声明:function 函数名(参数) { 函数体 },支持函数提升(可在定义前调用)。
  • 函数表达式:const 变量名 = function(参数) { 函数体 },无函数提升,需先定义后调用。

示例:

javascript

运行

复制代码
// 函数声明(支持提升)
function calculateSum(a, b) {
  return a + b;
}

// 函数表达式(无提升)
const calculateProduct = function(a, b) {
  return a * b;
};

箭头函数:语法糖简化,场景化省略

箭头函数仅支持表达式定义(需赋值给变量),用=>替代function,且可根据场景省略语法元素:

  • 单参数可省略括号:const double = num => num * 2
  • 单行表达式可省略花括号和returnconst add = (a, b) => a + b
  • 无参数需写空括号:const getNow = () => new Date()
  • 多行函数体需保留花括号和returnconst formatStr = str => { const newStr = str.trim(); return newStr.toUpperCase(); }

示例对比:

javascript

运行

复制代码
// 普通函数
function filterEven(arr) {
  return arr.filter(function(item) {
    return item % 2 === 0;
  });
}

// 箭头函数(嵌套简化)
const filterEven = arr => arr.filter(item => item % 2 === 0);

二、核心区别:this 指向机制(最关键差异)

this的绑定规则是两种函数的核心分歧,直接决定了它们的适用场景。

普通函数:动态绑定,指向调用者

普通函数的this调用时 确定,指向触发函数执行的 "调用者",且可通过callapplybind手动修改:

  • 全局调用(非严格模式):this指向全局对象(浏览器为window,Node.js 为global)。
  • 作为对象方法调用:this指向该对象。
  • 构造函数调用(new关键字):this指向新创建的实例。
  • 事件绑定调用:this指向绑定事件的 DOM 元素。

示例:

javascript

运行

复制代码
const user = {
  name: "张三",
  sayName: function() {
    console.log(this.name); // 指向user对象,输出"张三"
  }
};

function showThis() {
  console.log(this);
}
showThis(); // 全局调用,输出window(浏览器环境)
showThis.call(user); // 手动绑定,输出user对象

箭头函数:静态绑定,继承外层作用域

箭头函数没有自己的this ,其this定义时 就已确定,直接继承外层作用域的this,且后续无法修改:

  • 无论通过何种方式调用,this都不会改变。
  • 不存在 "调用者绑定""构造函数绑定" 等规则。
  • 无法通过callapplybind修改this指向(传入的第一个参数会被忽略)。

示例:

javascript

运行

复制代码
const user = {
  name: "张三",
  sayName: () => {
    console.log(this.name); // 继承全局this,输出undefined(浏览器环境)
  },
  asyncSayName: function() {
    setTimeout(() => {
      console.log(this.name); // 继承asyncSayName的this(user对象),输出"张三"
    }, 1000);
  }
};
user.sayName(); // 输出undefined
user.asyncSayName(); // 输出"张三"

三、功能特性:构造能力与原型差异

两种函数在实例创建、原型属性等功能上的差异,进一步明确了它们的使用边界。

普通函数:支持构造实例,拥有原型

普通函数可作为构造函数使用,通过new关键字创建对象实例,且自带prototype属性(支持原型继承):

javascript

运行

复制代码
// 普通函数作为构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 原型上添加方法(所有实例共享)
Person.prototype.sayInfo = function() {
  console.log(`${this.name},${this.age}岁`);
};

const person1 = new Person("李四", 25);
person1.sayInfo(); // 输出"李四,25岁"
console.log(Person.prototype); // 存在原型对象

箭头函数:不可构造,无原型属性

箭头函数因缺少自身thisprototype属性,无法作为构造函数使用:

  • new调用箭头函数会抛出TypeError
  • 箭头函数的prototype属性为undefined,无法实现原型继承。

示例:

javascript

运行

复制代码
const Person = (name, age) => {
  this.name = name; // 无效,this指向外层作用域
};

// 报错:Person is not a constructor
const person2 = new Person("王五", 30);
console.log(Person.prototype); // 输出undefined

四、补充差异:arguments 与绑定方法

除核心特性外,二者在参数获取、特殊方法支持上还有细节区别:

arguments 对象

  • 普通函数:支持arguments对象,可获取所有传入参数(类数组形式)。
  • 箭头函数:无arguments对象,需通过 "剩余参数"(...args)获取参数。

示例:

javascript

运行

复制代码
// 普通函数:使用arguments
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

// 箭头函数:使用剩余参数
const sumArrow = (...args) => {
  return args.reduce((total, curr) => total + curr, 0);
};
console.log(sumArrow(1, 2, 3, 4)); // 输出10

call/apply/bind 的作用

  • 普通函数:这三个方法可修改this指向,并执行或返回新函数。
  • 箭头函数:这三个方法仅能传递参数,无法修改thisthis仍继承外层)。

示例:

javascript

运行

复制代码
const obj1 = { value: 10 };
const obj2 = { value: 20 };

// 普通函数
function getValue() {
  return this.value;
}
console.log(getValue.call(obj1)); // 输出10(this指向obj1)

// 箭头函数
const getValueArrow = () => this.value;
console.log(getValueArrow.call(obj2)); // 输出undefined(this仍指向全局)

五、实战选型:场景决定用法

两种函数无绝对优劣,需根据场景灵活选择:

优先使用箭头函数的场景

  • 回调函数(数组遍历、定时器、Promise):避免this丢失。

    javascript

    运行

    复制代码
    // 数组遍历
    const arr = [1, 2, 3];
    const doubled = arr.map(item => item * 2);
    
    // Promise回调
    fetch("/api/data")
      .then(res => res.json())
      .catch(err => console.error(err));
  • 简单逻辑函数(纯计算、数据格式化):语法简洁,无需this

    javascript

    运行

    复制代码
    const formatDate = date => date.toLocaleDateString("zh-CN");

必须使用普通函数的场景

  • 构造函数(创建实例):需this绑定实例和原型继承。

  • 对象方法:需通过this访问对象自身属性。

    javascript

    运行

    复制代码
    const calculator = {
      num: 0,
      add: function(value) {
        this.num += value; // this指向calculator
        return this.num;
      }
    };
  • 需使用arguments或原型的场景:箭头函数不支持这些特性。

总结:核心差异速查表

对比维度 普通函数 箭头函数
语法结构 function关键字,支持声明 / 表达式 =>,仅支持表达式
this指向 调用时动态绑定(指向调用者) 定义时静态绑定(继承外层)
构造能力 new调用,有prototype 不可new,无prototype
arguments 对象 支持 不支持(用剩余参数替代)
适用场景 构造函数、对象方法、复杂逻辑 回调函数、纯函数、简单逻辑

要不要我帮你整理一份箭头函数与普通函数差异对比表(Markdown 格式),方便你直接嵌入博客或打印参考?

相关推荐
沐知全栈开发4 小时前
HTML5 浏览器支持
开发语言
wasp5204 小时前
AgentScope Java 核心架构深度解析
java·开发语言·人工智能·架构·agentscope
WHOVENLY4 小时前
【javaScript】- 笔试题合集(长期更新,建议收藏,目前已更新至31题)
开发语言·前端·javascript
慌糖4 小时前
流-为序列化解释
开发语言
指尖跳动的光4 小时前
将多次提交合并成一次提交
前端·javascript
若梦plus4 小时前
JS之类型化数组
前端·javascript
若梦plus4 小时前
Canvas 深入解析:从基础到实战
前端·javascript
若梦plus4 小时前
Canvas渲染原理与浏览器图形管线
前端·javascript
LXS_3575 小时前
Day 18 C++提高 之 STL常用容器(string、vector、deque)
开发语言·c++·笔记·学习方法·改行学it