news 2026/4/17 1:57:30

箭头函数 vs 普通函数:前端新人别再被 this 搞懵了!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
箭头函数 vs 普通函数:前端新人别再被 this 搞懵了!


箭头函数 vs 普通函数:前端新人别再被 this 搞懵了!

  • 箭头函数 vs 普通函数:前端新人别再被 this 搞懵了!
    • 先整点废话,不然不长记性
    • 混个脸熟:箭头函数到底长啥样?
    • this 的归属权大战:谁调用我 vs 我在哪出生
      • 普通函数:谁最后点我,我就是谁的 this
      • 箭头函数:我在哪儿定义,this 就永远锁死在外层
      • 真实翻车现场 1:定时器里写箭头,this 直接蒸发
      • 真实翻车现场 2:React 类组件事件里用普通函数,this 失踪
    • arguments 对象?箭头函数说:我没见过这玩意儿
    • 不能当构造函数:new 一个箭头函数,浏览器直接甩脸
    • super 和 new.target:箭头函数表示我借不到
    • 实战:到底哪里该用谁?一张表给你整明白
    • 排查 this 不对劲的三板斧
    • 小机灵鬼技巧合集
      • 1. forEach 里再也不用写 `const that = this`
      • 2. 立即执行箭头函数,做模块隔离
      • 3. 统一工具库风格,全箭头,可读性高
      • 4. 骚操作:用箭头函数写“自解耦”定时器
    • 彩蛋时间:你以为箭头函数不能 async?错!
    • 最后一碗毒鸡汤

箭头函数 vs 普通函数:前端新人别再被 this 搞懵了!

友情提示:本文全程口语化,代码管饱,吐槽拉满,建议配着肥宅快乐水服用,边喝边骂“卧槽原来如此”。


先整点废话,不然不长记性

那天凌晨一点,我盯着屏幕上的Cannot read property 'setState' of undefined发呆,心里把 React 作者全家问候了个遍。结果第二天早上一查,罪魁祸首居然是我自己写的箭头函数——写是写得爽,this 直接原地蒸发。那一刻我悟了:不是所有长得像函数的玩意儿,都能当函数使。


混个脸熟:箭头函数到底长啥样?

先别整那些八股定义,咱直接上代码,一眼看出谁是谁:

// 普通函数,老派写法functionadd(a,b){returna+b;}// 箭头函数,新式写法constadd=(a,b)=>a+b;

看着差不多,但坑就藏在“差不多”里。给你几个“简写陷阱”,踩过的人才懂:

// 1. 单参数,括号可省,但别省出歧义constdouble=x=>x*2;// OKconstdouble=(x)=>x*2;// 也 OK,看心情// 2. 多行语句,必须加大括号,否则隐式 return 给你 undefinedconstcalc=(a,b)=>{// 大括号一出现,return 就得手写constsum=a+b;returnsum*2;};// 3. 返回对象字面量,括号不能省,否则语法报错constgetUser=()=>({name:'kimi',age:18});// 小括号保命

小总结:箭头函数省字符,但省得太多,浏览器就帮你“省”掉工资。


this 的归属权大战:谁调用我 vs 我在哪出生

普通函数:谁最后点我,我就是谁的 this

constobj={name:'obj',normalFn:function(){console.log(this.name);}};obj.normalFn();// 'obj',没毛病

箭头函数:我在哪儿定义,this 就永远锁死在外层

constobj={name:'obj',arrowFn:()=>{console.log(this.name);// 外层是 window,this === window}};obj.arrowFn();// undefined(浏览器里 window.name 是空)

真实翻车现场 1:定时器里写箭头,this 直接蒸发

classCounter{constructor(){this.count=0;// 错误示范:箭头函数把 this 绑死在 windowsetInterval(()=>{this.count++;// 这里 this 其实是 Counter 实例,因为定义在构造函数里console.log(this.count);},1000);}}

等等,上面这段居然能跑?对,因为箭头函数定义在 constructor 内部,外层 this 就是实例。
但如果把箭头函数写到原型链上,再拿去当回调,就全凉了——后面 class 章节给你演示。

真实翻车现场 2:React 类组件事件里用普通函数,this 失踪

class Button extends React.Component { state = { clicks: 0 }; // 普通函数:事件回调里 this === undefined(严格模式) handleClick() { this.setState({ clicks: this.state.clicks + 1 }); // 报错 } render() { return <button onClick={this.handleClick}>点我</button>; } }

解决姿势三选一:

// 1. 构造函数里手动 bind(老干部写法) constructor() { super(); this.handleClick = this.handleClick.bind(this); } // 2. 类字段 + 箭头函数(现在最流行) handleClick = () => { this.setState({ clicks: this.state.clicks + 1 }); }; // 3. 回调里直接包箭头(适合一次性) onClick={() => this.handleClick()}

arguments 对象?箭头函数说:我没见过这玩意儿

普通函数自带arguments,长得像数组,其实是对象,坑死强迫症:

functionsum(){// 不是数组,不能用 mapconsole.log(arguments);// { '0': 1, '1': 2, '2': 3 }returnArray.from(arguments).reduce((a,b)=>a+b,0);}sum(1,2,3);// 6

箭头函数里写arguments会直接引用外层,一不留神就全局翻车:

constsum=()=>{console.log(arguments);// 引用外层,浏览器里就是 window.arguments,undefined};

正确姿势:用 rest 参数,真·数组,真·香:

constsum=(...nums)=>nums.reduce((a,b)=>a+b,0);sum(1,2,3);// 6

不能当构造函数:new 一个箭头函数,浏览器直接甩脸

constPerson=(name)=>{this.name=name;};constp=newPerson('kimi');// TypeError: Person is not a constructor

为啥?

  1. 箭头函数没有prototype属性,引擎层面就禁止[[Construct]]
  2. 设计者初衷:箭头函数只做“轻量匿名回调”,不想让你搞出花来。

super 和 new.target:箭头函数表示我借不到

普通函数里你可以:

classA{constructor(){console.log(new.target);// 指向真正被 new 的构造函数}}

箭头函数里写new.target会直接报错——它压根就没有自己的执行上下文,全蹭外层的。
继承场景下更惨:

classA{foo(){return()=>{console.log(super.bar);// 报错,箭头函数没有 super};}}

实战:到底哪里该用谁?一张表给你整明白

场景推荐理由
React 类组件事件处理器箭头函数(类字段写法)自动锁 this,不写 bind
对象方法普通函数需要动态 this
定时器/延时器回调箭头函数继承外层 this,省 bind
构造函数普通函数箭头函数不能 new
数组高阶方法回调箭头函数简短、无 this 绑定需求
需要 arguments普通函数 或 rest箭头函数无 arguments
类的方法(原型链)普通函数让子类可重写,避免 this 固化

排查 this 不对劲的三板斧

  1. 看函数是不是箭头:是箭头就死心吧,this 改不了。
  2. 看定义位置:箭头函数锁死外层 this,普通函数看调用。
  3. 看调用方式:有没有.bind(obj).call(obj).apply(obj)

快速调试黑魔法:

// 在可疑位置插桩console.log('当前 this 是:',this);// 浏览器里直接打断点,观察 Scope 链

小机灵鬼技巧合集

1. forEach 里再也不用写const that = this

// ES5 时代constthat=this;arr.forEach(function(item){that.doSomething(item);});// 现在arr.forEach(item=>this.doSomething(item));

2. 立即执行箭头函数,做模块隔离

constutils=(()=>{constsecret='2333';return{getSecret:()=>secret};})();console.log(utils.getSecret());// 2333

3. 统一工具库风格,全箭头,可读性高

exportconstpipe=(...fns)=>x=>fns.reduce((v,f)=>f(v),x);exportconstdebounce=(fn,ms)=>{letid;return(...args)=>{clearTimeout(id);id=setTimeout(()=>fn(...args),ms);};};

4. 骚操作:用箭头函数写“自解耦”定时器

classSlider{start(){this.timer=setInterval(()=>{this.next();// this 永远是实例,不怕被换掉},3000);}next(){console.log('next slide');}}

彩蛋时间:你以为箭头函数不能 async?错!

// 完全可以,但别写换行搞混constfetchUser=asyncid=>{constres=awaitfetch(`/api/user/${id}`);returnres.json();};

Generator 才真的不行——因为箭头函数不能用yield

constgen=*()=>{yield1;};// SyntaxError

最后一碗毒鸡汤

箭头函数就像泡面:方便、省事儿,但天天吃会营养不良。
普通函数像自己下厨:麻烦、锅碗瓢盆,但想炒啥都行。
写代码别炫技,可读性第一,性能第二,炫技排最后。
记住:当你纠结“用箭头还是普通”时,先问自己——“我需不需要动态 this?”
一句话总结:
要绑死 this → 箭头;要动态 this → 普通;要 new → 普通;要 arguments → 普通或 rest。
背不下来?抄桌子板上,下次报错直接翻,别再凌晨一点骂娘了。

写完收工,键盘上都是头发,点个赞再走吧,祝你永远不写undefined of undefined

欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 23:56:47

电商系统秒杀场景下的TransmittableThreadLocal实践

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个电商秒杀系统demo&#xff0c;要求&#xff1a;1) 使用SpringBoot框架 2) 集成TransmittableThreadLocal传递用户Token 3) 模拟1000并发请求 4) 对比普通ThreadLocal的效果…

作者头像 李华
网站建设 2026/4/15 22:58:36

MGeo模型调参实战:预装PyTorch的云端实验室

MGeo模型调参实战&#xff1a;预装PyTorch的云端实验室 引言&#xff1a;当AI研究员遇上地址匹配难题 作为一名经常需要处理地理空间数据的AI研究员&#xff0c;我最近遇到了一个典型的技术瓶颈&#xff1a;需要在地址匹配任务上对比MGeo模型在不同超参数下的表现&#xff0c;但…

作者头像 李华
网站建设 2026/4/16 21:45:51

Z-Image-Turbo中国风传统绘画风格适配度

Z-Image-Turbo中国风传统绘画风格适配度 阿里通义Z-Image-Turbo WebUI图像快速生成模型 二次开发构建by科哥 阿里通义推出的 Z-Image-Turbo 是一款基于扩散模型的高性能AI图像生成系统&#xff0c;具备极快推理速度与高质量输出能力。由开发者“科哥”进行深度二次开发后&#…

作者头像 李华
网站建设 2026/4/16 15:07:57

awk:对文本内容去重

案例一 样本数据 ES11 ES15 ED13 ED15 ES1Z ED11 SZ13 SZ15 ED13 SB15 SB13 BT23 DZ19 IT39 SZ13 IU23 IT23 GZ13 GZ15 IJ13 IU21 JS13 IH13 BT25 ED11 ED13 ED15 EJ15 ES11 IT25 IU25 JS15 SV15去重命令&#xff1a; awk {arr[$1];if(arr[$1] 1){print}} 11.txt案例二 样本数…

作者头像 李华
网站建设 2026/4/15 13:13:39

导入WordPress粘贴图片CMS系统自动压缩处理

要求&#xff1a;开源&#xff0c;免费&#xff0c;技术支持 博客&#xff1a;WordPress 开发语言&#xff1a;PHP 数据库&#xff1a;MySQL 功能&#xff1a;导入Word,导入Excel,导入PPT(PowerPoint),导入PDF,复制粘贴word,导入微信公众号内容,web截屏 平台&#xff1a;Window…

作者头像 李华
网站建设 2026/4/16 18:20:00

模型解释:在预装环境中可视化MGeo的地址匹配逻辑

模型解释&#xff1a;在预装环境中可视化MGeo的地址匹配逻辑 为什么需要可视化地址匹配逻辑 在实际业务场景中&#xff0c;我们经常会遇到这样的问题&#xff1a;两个看似不同的地址文本&#xff0c;却被系统判定为同一个地点。作为产品经理或技术人员&#xff0c;如何向客户解…

作者头像 李华