当前位置: 首页 > news >正文

箭头函数(Arrow Functions)和普通函数(Regular Functions)

在 JavaScript 中,箭头函数(Arrow Functions)和普通函数(Regular Functions)有以下主要区别:

1. 语法

  • 箭头函数:使用 => 语法,更简洁,可省略 function 和 return(单行表达式时)。

    // 普通函数
    function add(a, b) { return a + b; }// 箭头函数
    const add = (a, b) => a + b;
    
  • 普通函数:使用 function 关键字定义。

    function sayHello() {console.log("Hello");
    }
    

2. this 指向

  • 箭头函数

    • 不绑定 this,继承自父级作用域(定义时的上下文)。
    • 适合不需要自己上下文的场景(如回调函数)。
    const obj = {name: "Alice",greet: function() {setTimeout(() => {console.log(`Hello, ${this.name}`); // 继承自 greet() 的 this}, 1000);}
    };
    obj.greet(); // "Hello, Alice"
    
  • 普通函数

    • 绑定自己的 this,指向调用该函数的对象(或全局对象 / 严格模式下为 undefined)。
    const obj = {name: "Bob",greet: function() {setTimeout(function() {console.log(`Hello, ${this.name}`); // this 指向全局对象或 undefined}, 1000);}
    };
    obj.greet(); // "Hello, undefined" 或报错
    

3. arguments 对象

  • 箭头函数

    • 没有自己的 arguments 对象,继承自父级作用域。
    const sum = () => {console.log(arguments); // 报错或引用外层的 arguments
    };
    sum(1, 2); // 错误:arguments 未定义
    
  • 普通函数

    • 有自己的 arguments 对象,包含调用时的参数。
    function sum() {return arguments[0] + arguments[1];
    }
    sum(1, 2); // 3
    

4. 使用限制

  • 箭头函数

    • 不能使用 argumentssuper 或 new.target
    • 不能使用 yield(不能用作生成器)。
    • 不能使用 new 实例化(没有 [[Construct]] 方法)。
    const ArrowClass = () => {};
    new ArrowClass(); // 错误:箭头函数不能用作构造函数
    
  • 普通函数

    • 可以使用 argumentssupernew.target 和 yield
    • 可以使用 new 实例化(作为构造函数)。
    function RegularClass() {this.value = 42;
    }
    const instance = new RegularClass();
    

5. yield 和 await

  • 箭头函数

    • 不能单独使用 yield(除非在生成器函数内部)。
    • 可以使用 await,但需要在 async 箭头函数中。
    const fetchData = async () => {const response = await fetch("api/data");return response.json();
    };
    
  • 普通函数

    • 可以使用 yield 定义生成器函数。
    function* generator() {yield 1;yield 2;
    }
    

6. 适用场景

  • 箭头函数

    • 简单的回调函数(如 mapfiltersetTimeout)。
    • 需要保留父级 this 的场景。
    • 单行逻辑的函数。
  • 普通函数

    • 构造函数(需要创建实例)。
    • 需要动态 this 绑定的场景(如方法、事件处理)。
    • 需要使用 arguments 对象的场景。

总结对比表

特性箭头函数普通函数
语法简洁,使用 =>完整,使用 function
this 指向继承自父级作用域动态绑定(调用者)
arguments 对象
能否使用 new
能否使用 yield否(除非在生成器内)
适用场景回调函数、需要保留 this构造函数、动态 this 绑定

如何理解this 指向 箭头函数的this继承自父级作用域 普通函数的this是动态绑定(调用者)

要理解 this 指向的差异,关键在于抓住箭头函数的 this 是 “静态绑定”(定义时确定),而普通函数的 this 是 “动态绑定”(调用时确定) 这一核心区别。下面通过具体场景和例子展开说明:

一、箭头函数:this 继承自父级作用域(定义时确定)

箭头函数没有自己的 this,它的 this 是在定义函数时就固定好的,等于父级作用域(外层代码块)的 this,且永远不会改变。

可以理解为:箭头函数的 this 是 “抄” 父级的,一旦定义就 “锁死”,后续无论怎么调用,this 都不会变。

例子 1:对象方法中的箭头函数

javascript

const obj = {name: "Alice",// 普通函数作为方法(父级作用域)getParentThis: function() {// 箭头函数定义在 getParentThis 内部,父级作用域是 getParentThis 的 thisconst arrowFunc = () => {console.log(this.name); // this 继承自 getParentThis 的 this(即 obj)};return arrowFunc;}
};const func = obj.getParentThis(); 
func(); // 输出 "Alice"(箭头函数的 this 是定义时的父级 this,即 obj)

  • 箭头函数 arrowFunc 定义在 getParentThis 内部,父级作用域的 this 是 obj(因为 getParentThis 是 obj 调用的),所以箭头函数的 this 就是 obj
  • 即使后续用其他方式调用 func(如 func.call(otherObj)),this 也不会变,始终是 obj
例子 2:全局作用域中的箭头函数

javascript

// 全局作用域的 this 是 window(浏览器环境)
const globalArrow = () => {console.log(this === window); // 输出 true(继承全局作用域的 this)
};globalArrow(); 
const obj = { fn: globalArrow };
obj.fn(); // 依然输出 true(箭头函数的 this 不会因调用者变化而改变)

二、普通函数:this 是动态绑定(调用时确定,由调用者决定)

普通函数的 this 是在调用函数时才确定的,取决于 “谁调用了它”,即 “调用者”。调用方式不同,this 指向就可能不同。

常见的调用场景决定 this 指向的规则:

  1. 直接调用(如 fn()):this 指向全局对象(浏览器中是 window,Node 中是 global;严格模式下为 undefined)。
  2. 作为对象方法调用(如 obj.fn()):this 指向该对象(obj)。
  3. 用 call/apply/bind 调用this 指向传入的第一个参数。
  4. 作为构造函数调用(如 new Fn()):this 指向新创建的实例对象。
例子 1:不同调用方式下的普通函数 this

javascript

function regularFunc() {console.log(this.name);
}const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };// 1. 直接调用:this 指向全局(无 name 属性,输出 undefined)
regularFunc(); // undefined// 2. 作为对象方法调用:this 指向调用的对象
obj1.fn = regularFunc;
obj1.fn(); // 输出 "obj1"(this 是 obj1)// 3. 用 call 强制绑定:this 指向传入的 obj2
regularFunc.call(obj2); // 输出 "obj2"
例子 2:对比箭头函数和普通函数在回调中的差异

最典型的场景是定时器回调:

javascript

const person = {name: "Bob",// 普通函数作为方法sayHi: function() {// 1. 普通函数作为回调:this 指向全局(调用者是定时器,非 person)setTimeout(function() {console.log("普通函数回调:", this.name); // undefined(this 是 window)}, 100);// 2. 箭头函数作为回调:this 继承自 sayHi 的 this(即 person)setTimeout(() => {console.log("箭头函数回调:", this.name); // "Bob"(this 是 person)}, 100);}
};person.sayHi(); 

  • 普通函数的回调:调用者是定时器(浏览器中是 window),所以 this 指向 window
  • 箭头函数的回调:定义在 sayHi 内部,父级 sayHi 的 this 是 person,所以箭头函数的 this 也是 person

总结:核心区别一句话

  • 箭头函数this 是 “定义时抄父级的”,一旦确定就不变(静态绑定)。
  • 普通函数this 是 “调用时看是谁调的”,调用方式变了,this 就可能变(动态绑定)。

记住这个区别,就能避开大多数 this 指向的坑。

http://www.lryc.cn/news/586178.html

相关文章:

  • 虚拟现实的镜廊:当技术成为存在之茧
  • 云端docker小知识
  • Java 大视界:基于 Java 的大数据可视化在智慧城市能源消耗动态监测与优化决策中的应用(2025 实战全景)
  • YOLO家族内战!v5/v8/v10谁才是你的真命天子?(附保姆级选择指南)
  • CCS-MSPM0G3507-2-定时器中断
  • 傅里叶方法求解正方形区域拉普拉斯方程
  • LeetCode经典题解:3、无重复字符的最长子串
  • jenkins自动化部署前端vue+docker项目
  • 洛谷 P11961 [GESP202503 五级] 原根判断-提高+/省选-
  • 【设计模式】单例模式 饿汉式单例与懒汉式单例
  • 玩转rhel9 Apache
  • 关于两种网络攻击方式XSS和CSRF
  • 剑指offer57_和为S的两个数字
  • script中crossorigin=“anonymous“是什么意思
  • Redis专题总结
  • 构建AI Agent的完整实战指南:从邮件助手案例看6步落地方法
  • docker基础与常用命令
  • Linux之Zabbix分布式监控篇(一)
  • Elasticsearch 的 `modules` 目录
  • Git常用命令一览
  • 中德英法西五语氛围刷题第一集:HTML命名空间CSS处理
  • Python问题记录`No module named ‘matplotlib‘` 问题解决方案
  • 苍穹外卖项目日记(day05)
  • UI前端大数据可视化实战策略分享:如何设计符合用户认知的数据可视化流程?
  • 以数据为核心,以业务为导向,漫谈数据可视化应用
  • 上门服务APP开发源码商业模式设计与功能架构解析
  • QCustomPlot绘制交互图
  • Django母婴商城项目实践(四)
  • JavaSE 01 类和对象|继承多态
  • Java_Springboot技术框架讲解部分(一)