惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
Jina AI
Jina AI
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
博客园 - 司徒正美
罗磊的独立博客
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
Vercel News
Vercel News
A
About on SuperTechFans
I
InfoQ
D
DataBreaches.Net
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队

Mereith's Blog

记一次代理转发问题的排查与解决 PVE DataCenter Manager 端口号跳转错误修复 k8s + jenkins + gitlab 触发器 【转载】没有编程生产力这样的东西 【后续】居然被 ddos 了 居然被 ddos 了 Tagger - 让版本标签管理更简单 openclash 开启后端口转发失效 nextjs 启动时执行代码 买了太多VPS不知道干什么,干脆做个网站 juhost Level-1 测评 VMISS CN - Hong Kong VMISS JP - Tokyo - BGP 测评 VMISS CN - Hong Kong - BGP HomeLab 的终点是 最近在做的事情 因为选择艰难症,自己写了一套开源博客系统 手撸一个nodejs分布式爬虫,还要可视化 HomeLab 分享 我的个人工作流——开源项目推荐 动手写一个超简单的编译器 safari 插件开发 Safari Extensions Preferences 按钮无响应 设置移动端软键盘回车按钮文案 nginx proxy manager 非标准端口反代 Host 不对 监控 k8s ingress 自动添加域名 DNS 解析 使用 ingress 注解给 traefik ingress 添加中间件 使用流水线功能为文章添加固定结尾 为 VanBlog 添加一个小挂件 基于React/umi/egg自建博客系统 如何正确停止 NodeJS 子进程
js 防抖节流中的 this 与箭头函数
wanglu@mereith.com (mereith) · 2022-07-31 · via Mereith's Blog

请注意,本文编写于 1411 天前,最后修改于 1406 天前,其中某些信息可能已经过时。

参数问题

现象

背八股文的时候温习了一下防抖和节流的概念。于是自己随手把网上的版本试了一下,发现不行:

<body> <button id="debounce">防抖测试</button> <script> function debounce(fn, delay) { let timer = null; return function () { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this) }, delay) } } document.querySelector("#debounce").addEventListener("click", debounce((ev) => { console.log(ev) }, 500)) </script> </body>

控制台会打印 undefined

结论

setTimeout 里我们的函数执行的时候,没有参数。所以应该改为:

timer = setTimeout(() => { fn.apply(this,arguments) }, delay)

所以里面的 apply 可以通俗的理解为就是为了传参数进去用的。

但为什么这样就可以呢?为啥arguments 就对了呢?

箭头函数

试验1

setTimeout 里面用的是箭头函数,那我们用普通函数会发生什么?

timer = setTimeout(function () { fn.apply(this,arguments) }, delay)

控制台会打印:


试验2

我们修改一下代码:

function debounce(fn, delay) { let timer = null; return function () { console.log(this,arguments); setTimeout(function () { console.log(this,arguments); },delay) setTimeout(()=>{ console.log(this,arguments); },delay) } }

控制台会输出:

分析

从两个试验可以看出,箭头函数会把内部的 thisarguments 绑定为与定义时的上层一致。

而上一层就是我们的事件监听器直接调用的函数,所以这时候的 argumentsthis 都是正确的。

知识点

  1. 作为普通函数执行时,this 指向 window。如果是事件监听,就是触发事件的对象。
  2. 当函数作为对象的方法被调用时,this 就会指向该对象。
  3. 构造器调用,this 指向返回的这个对象。
  4. 箭头函数的 this 绑定看的是 this 所在函数定义在哪个对象下,就绑定哪个对象。如果有嵌套的情况,则 this 绑定到最近的一层对象上。
  5. 基于 Function.prototype 上的 applycallbind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。apply 接收参数的是数组,call 接受参数列表,bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变。若为空默认是指向全局对象 window