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