(鸡汤文)这一次我终于搞懂了 JavaScript 定时器的 this 指向!
开篇语
忽然有一种感觉,每次学习一个知识点就像是谈一场恋爱:从初次邂逅,到彼此了解,一切都那么的符合恋爱的过程!
如果这个知识点再有点”调皮“的话,那简直是让人欲仙欲死而又不可自拔!因为你永远不知道它还有多少面纱等着你揭开,当你自以为对它已经足够了解的时候,冷不防就是一个盲点迎面砸来。
它简直就像一个”宝藏女孩“,你要时刻做好迎接”惊喜“的准备!
可能正是因为这种新鲜感,我才能一直保持一种类似亢奋的状态吧。当然,这只是针对知识而言,对待情感我还是很保守很专一的<( ̄︶ ̄)>
这两天,我就在和定时器谈恋爱,哦不,是在学习定时器( ̄▽ ̄)~*,可没想到,又给陷进去了……
这不,上一篇文章写完定时器的返回值后,刚觉得自己对它已经了解的清清楚楚明明白白了,够我炫耀一阵子了,谁成想,喘口气的功夫,它又给我整出了幺蛾子。
惑起
写完上篇文章后,我就琢磨着里面的实现代码还可以优化一下,于是给改成了下面这个样子:
<form action="" class="example-form"> <div> <label for="name"> 名称 </label> <input class="input-ele" type="text" name="name" id="name" placeholder="please input your name" autocomplete="off"> </div> <div style="margin-top:50px;"> <label for="res"> 输入 </label> <textarea class="input-ele" type="multipart" name="res" id="res" readonly placeholder="这里是每一次输入的结果"></textarea> </div> </form> <script> window.onload = function () { const resEle = document.querySelector("#res"); function changeOutputVal() { resEle.value += `\n${ this.value }`; } function throttle(fun, delay) { let last, deferTimer return function () { let now = Date.now(); if (last && now < last + delay) { clearTimeout(deferTimer); deferTimer = setTimeout(function () { last = now; fun.apply(this); }, delay) } else { last = now; fun.apply(this); } } } const inputEle = document.querySelector("#name"); inputEle.addEventListener("input", throttle(changeOutputVal, 1000)); } </script>
我的修改依据是:
- throttle 方法返回的是一个匿名函数,这个函数正好充当 input 事件的回调函数
- input 事件回调函数中的 this 指向的是 inputEle
- 匿名函数中将 this 绑定给了 fun 参数,而实际使用中传入的是 changeOutputVal 方法
- 所以 changeOutputVal 方法中的 this 指的就是 inputEle,所以在它里面可以通过
this.value
获取到 inputEle 的值
看,这逻辑多严谨,简直头头是道啊 \( ̄︶ ̄)/
按理说,是没问题的吧,结果却出问题了。欲知详情,请看大屏幕:
这个 undefined 是什么鬼?!从哪冒出来的?难道我的延时器没用对?
解惑
面对我的质疑,setTimeout 理直气壮地说:人家回调函数中的 this 本来就是指向 window 对象的嘛,你也没早问啊!
那么,问题来了:为什么延时器中的 this 指向的是 window 呢?setTimeout 自己也解释不清楚了。
得,看来前人诚不我欺也——自己动手,丰衣足食!
凡事不决找 MDN,绝对靠谱!我们来看看 MDN 怎么说:
由
setTimeout()
调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的this
关键字在非严格模式会指向window
(或全局)对象,严格模式下为 undefined,这和所期望的this
的值是不一样的。
看到这个解释,我才明白:this 指向 window 对象,原来是因为执行环境的不同导致的。
在上面的代码中,因为 window 对象没有 value 这个属性,所以 window.value = undefined
。
感觉自己在专业的方向上又迈进了一小步,容我小小地嘚瑟一下!
改错
既然知道问题出在哪,那就好办了,我们只需要将 setTimeout 回到函数内部的 this 指向改变一下就好,这里有以下方案。
使用变量引用外部 this
关键代码如下:
window.onload = function () { // some code here const that = this; deferTimer = setTimeout(function () { last = now; fun.apply(that); }, delay) // some code here }
使用箭头函数
利用箭头函数不会改变 this 的指向的特性,改造如下:
window.onload = function () { // some code here deferTimer = setTimeout(() => { last = now; fun.apply(this); }, delay) // some code here }
结束语
知错能改,善莫大焉!
写到这里,我居然体会到了古人那种”朝闻道,夕死可矣“的满足感。
在编程这条路上,可能遍布荆棘,但只要我们勤耕不辍,总能开辟出属于自己的康庄大道!
这鸡汤太美味,我先干为敬,你们随意!b( ̄▽ ̄)d
~
~
~ 本文完,感谢阅读!
~
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!
你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
php7和php8在OpenLiteSpeed、nginx上的性能测试(包括是否开启opcache)
php8出来有一段时间了,被吹的神乎其神,正好今天在家哄孩子有点时间就测试了一下性能。 测试服务器为阿里云2核2G,其实测试的都是单核性能,几核几G其实关系不大。测试代码还是直接使用的以前的代码。如下。 <?php function msec() { list($sec,$msec) = explode(' ', microtime()); return (floatval($sec) + floatval($msec)) ; } $s_time = msec(); function fib($n) { if ($n == 1 || $n == 2) { return 1; } return fib($n - 1) + fib($n - 2); } echo fib(40); $e_time = msec(); echo '<br>'; echo $e_time - $s_time; OpenLiteSpeed版本为 1.6.21,php版本是7.4和8.0,ngnix版本为1.20,全部是编译安装。测试结果如下。 环境 正常...
- 下一篇
百度一款前端图片合成工具库 MI 开源啦!
什么是 MI Mi 全称 mix-img,是一个前端图片合成工具库,它可以将多张图片和文字合成一个全新的图片。作为一个轻量级的图片合成解决方案,Mi 支持多张图片并行加载合成,减少图片合成时间,提升前端开发者的开发效率,改善开发体验。 MI 能做什么 随着互联网业务的发展,用户接触的信息也越来越多,越来越丰富。生动的图片相对简单的文字也更能够吸引用户的关注。而互联网海量的用户有不同的属性和兴趣,个性化展示图片、分享图片的场景应运而生。基于以上原因,Mi(mix-img)诞生了。 Mi 的核心价值在于能够通过简单的配置输入将多张图片或者文字快速的合并成一张图片展示给用户或者用于分享炫耀场景。 Mi 在图片和文字的样式处理上也足够完善,包括支持产出不同尺寸、不同类型的图片,图片的圆角处理。还有对文字颜色、位置的处理。同时也支持在图片中加入二维码的元素。 MI 的特点 并行加载图片资源使合成速度更快 内置二维码功能,直接配置就能将二维码合成到图片上,不用开发者单独处理 支持图片压缩 默认增加缓存处理,同样配置图片直接返回结果而不是重新合成 对开发者友好,包括支持调试、文字变量替...
相关文章
文章评论
共有0条评论来说两句吧...