箭头函数(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 = {                      // 全局作用域(Global Scope)name: "Alice",                   // obj 对象作用域(Object Scope)greet: function() {              // greet 方法作用域(Function Scope)setTimeout(() => {             // 箭头函数作用域(Arrow Function Scope)console.log(`Hello, ${this.name}`);}, 1000);}
      };
      obj.greet();

    • 箭头函数的 this 继承自哪里?
      箭头函数的 this 继承自它被定义时的外层作用域的 this(即 greet 函数的 this),而 不是 继承外层函数(greet)本身。

      • greet 是一个普通函数,它的 this 由调用方式决定(obj.greet() 所以 this = obj)。

      • 箭头函数继承了 greet 的 this(即 obj),而不是 greet 函数对象。

    • 为什么不是指向 greet 函数?

      • 函数本身的 this 和函数对象是 完全不同的概念

      • greet 作为函数对象时,它的名字是 greet,但它的 this 是动态绑定的(这里是 obj)。

    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 () {console.log(this.name); // "Bob"setTimeout(function () {console.log(`Hello, ${this.name}`); // this 指向全局对象或 undefined}, 1000);}
    };
    obj.greet(); // "Hello, undefined" 或报错

  • const/let 声明的全局变量 不会 成为全局对象(如 window)的属性。

  • 只有 var 声明的变量或直接赋值到 this 的属性(如 window.age = 20)才会被 this.age 访问到。

var age = 20; // var 会挂载到 window
/// const age = 20 //const 是局部变量
const obj = {greet: function() {setTimeout(function() {console.log(this.age); // 20(this 指向 window)}, 1000);}
};
obj.greet();

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:对象方法中的箭头函数
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:全局作用域中的箭头函数
// 全局作用域的 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
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:对比箭头函数和普通函数在回调中的差异

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

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.pswp.cn/news/914385.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914385.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 配置注解处理器 - spring-boot-configuration-processor

前言 在 Spring Boot 开发中,配置属性的管理是构建企业级应用的核心环节。Spring Boot 通过 ConfigurationProperties 注解提供了一种类型安全的方式,将配置文件中的属性绑定到 Java 对象中。然而,开发者在使用过程中常会遇到配置属性无自动补…

java: DDD using oracle 21c

项目结构:domain:/*** encoding: utf-8* 版权所有 2025 ©涂聚文有限公司 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎* 描述:* Author : geovindu,Geovin Du 涂聚文.* IDE : IntelliJ IDEA 2024…

两张图片对比clip功能

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>图片拖动Clip对比功能</title><style&g…

7.11 dp 图

lcr148.栈按放入顺序推栈&#xff0c;能弹出的就及时弹出&#xff0c;最后栈空则符合要求。判断 takeOut 序列是否符合栈的操作逻辑&#xff0c;因为题目中“特殊的数据结构”其实就是栈&#xff08;先进后出&#xff09;。思路如下&#xff1a;1. 用一个栈来模拟图书放入的过程…

react16-react19都更新哪些内容?

React 16 到 React 19 是 React 发展非常关键的阶段&#xff0c;每个版本都带来了深远影响。以下是 React 16 → 19 的重要更新列表&#xff0c;按版本详细说明每一代的核心特性、重要变化、对开发者的意义&#xff0c;并附简评&#xff1a;✅ React 16&#xff08;2017 年&…

【AI大模型】RAG系统组件:向量数据库(ChromaDB)

RAG 系统中的关键组件&#xff1a;向量数据库&#xff08;Vector Database&#xff09;&#xff0c;并以 ChromaDB 为例进行说明。什么是向量数据库&#xff1f;核心概念&#xff1a; 向量数据库是一种专门设计用于高效存储、索引和检索高维向量的数据库。向量是什么&#xff1…

006_测试评估与安全实践

测试评估与安全实践 目录 建立成功标准评估方法测试策略安全最佳实践隐私保护性能监控 建立成功标准 定义原则 1. 具体明确 清晰定义精确目标避免模糊表述如"良好性能"制定可操作的标准 不好的标准&#xff1a; 模型应该表现良好好的标准&#xff1a; 情感分…

时序预测 | Pytorch实现CNN-KAN电力负荷时间序列预测模型

预测效果 代码功能 该代码实现了一个结合卷积神经网络&#xff08;CNN&#xff09;和Kolmogorov–Arnold网络&#xff08;KAN&#xff09;的混合模型&#xff08;CNN-KAN&#xff09;&#xff0c;用于时间序列预测任务。核心功能包括&#xff1a; 数据加载与预处理&#xff1…

UI前端与数字孪生结合实践探索:智慧物流的仓储优化与管理系统

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;仓储管理的 “数字孪生革命”传统物流仓储正面临 “效率瓶颈、可视化差、响应滞…

【Android】在平板上实现Rs485的数据通讯

前言 在工业控制领域&#xff0c;Android 设备通过 RS485 接口与 PLC&#xff08;可编程逻辑控制器&#xff09;通信是一种常见的技术方案。最近在实现一个项目需要和plc使用485进行通讯&#xff0c;记录下实现的方式。 我这边使用的从平的Android平板&#xff0c;从平里面已经…

MySQL技术笔记-备份与恢复完全指南

目录 前言 一、备份概述 &#xff08;一&#xff09;备份方式 &#xff08;二&#xff09;备份策略 二、物理备份及恢复 &#xff08;一&#xff09;备份操作 &#xff08;二&#xff09;恢复操作 三、逻辑备份及恢复 &#xff08;一&#xff09;逻辑备份 &#xff0…

SpringBoot或OpenFeign中 Jackson 配置参数名蛇形、小驼峰、大驼峰、自定义命名

SpringBoot或OpenFeign中 Jackson 配置参数名蛇形、小驼峰、大驼峰、自定义命名 前言 在调用外部接口时&#xff0c;对方给出的接口文档中&#xff0c;入参参数名一会大写加下划线&#xff0c;一会又是驼峰命名。 示例如下&#xff1a; {"MOF_DIV_CODE": "xx…

uni-app 途径站点组件开发与实现分享

在移动应用开发中&#xff0c;涉及到出行、物流等场景时&#xff0c;途径站点的展示是一个常见的需求。本文将为大家分享一个基于 uni-app 开发的途径站点组件&#xff0c;该组件能够清晰展示路线中的各个站点信息&#xff0c;包括站点名称、到达时间、是否已到达等状态&#x…

kotlin中集合的用法

从一个实际应用看起以下kotlin中代码语法正确吗 var testBeanAIP0200()var testList:List<AIP0200> ArrayList()testList.add(testBean)这段Kotlin代码存在语法错误&#xff0c;主要问题在于&#xff1a;List<AIP0200> 是Kotlin中的不可变集合接口&#xff0c;不能…

深入理解 Java Map 与 Set

文章目录前言1. 搜索树1.1 什么是搜索树1.2 查找1.3 插入1.4 删除情况一&#xff1a;cur 没有子节点&#xff08;即为叶子节点&#xff09;情况二&#xff1a;cur 只有一个子节点&#xff08;只有左子树或右子树&#xff09;情况三&#xff1a;cur 有两个子节点&#xff08;左右…

excel如何只保留前几行

方法一&#xff1a;手动删除多余行 选中你想保留的最后一行的下一行&#xff08;比如你只保留前10行&#xff0c;那选第11行&#xff09;。按住 Shift Ctrl ↓&#xff08;Windows&#xff09;或 Shift Command ↓&#xff08;Mac&#xff09;&#xff0c;选中从第11行到最…

实时连接,精准监控:风丘科技数据远程显示方案提升试验车队管理效率

风丘科技推出的数据远程实时显示方案更好地满足了客户对于试验车队远程实时监控的需求&#xff0c;并真正实现了试验车队的远程管理。随着新的数据记录仪软件IPEmotion RT和相应的跨平台显示解决方案的引入&#xff0c;让我们的客户端不仅可在线访问记录器系统状态&#xff0c;…

灰盒级SOA测试工具Parasoft SOAtest重新定义端到端测试

还在为脆弱的测试环境、强外部依赖和低效的测试复用拖慢交付而头疼&#xff1f;尤其在银行、医疗、制造等关键领域&#xff0c;传统的端到端测试常因环境不稳、接口难模拟、用例难共享而举步维艰。 灰盒级SOA测试工具Parasoft SOAtest以可视化编排简化复杂测试流程&#xff0c…

OKHttp 核心知识点详解

OKHttp 核心知识点详解 一、基本概念与架构 1. OKHttp 简介 类型&#xff1a;高效的HTTP客户端特点&#xff1a; 支持HTTP/2和SPDY&#xff08;多路复用&#xff09;连接池减少请求延迟透明的GZIP压缩响应缓存自动恢复网络故障2. 核心组件组件功能OkHttpClient客户端入口&#…

从“被动巡检”到“主动预警”:塔能物联运维平台重构路灯管理模式

从以往的‘被动巡检’转变至如今的‘主动预警’&#xff0c;塔能物联运维平台对路灯管理模式展开了重新构建。城市路灯属于极为重要的市政基础设施范畴&#xff0c;它的实际运行状态和市民出行安全以及城市形象有着直接且紧密的关联。不过呢&#xff0c;传统的路灯管理模式当下…