关于javascript:鸡汤文这一次我终于搞懂了-JavaScript-定时器的-this-指向

10次阅读

共计 2537 个字符,预计需要花费 7 分钟才能阅读完成。

开篇语

突然有一种感觉,每次学习一个知识点就像是谈一场恋爱:从首次邂逅,到彼此理解,所有都那么的合乎恋爱的过程!

如果这个知识点再有点”淘气“的话,那几乎是让人欲仙欲死而又不可自拔!因为你永远不晓得它还有多少面纱等着你揭开,当你自认为对它曾经足够理解的时候,冷不防就是一个盲点迎面砸来。

它几乎就像一个”宝藏女孩“,你要时刻做好迎接”惊喜“的筹备!

可能正是因为这种新鲜感,我能力始终放弃一种相似亢奋的状态吧。当然,这只是针对常识而言,看待情感我还是很激进很专一的 <(~︶~)>

这两天,我就在和定时器谈恋爱,哦不,是在学习定时器(~▽~)~*,可没想到,又给陷进去了……

这不,上一篇文章写完定时器的返回值后,刚感觉本人对它曾经理解的清清楚楚明明白白了,够我夸耀一阵子了,谁成想,喘口气的功夫,它又给我整出了幺蛾子。

惑起

写完上篇文章后,我就推敲着外面的实现代码还能够优化一下,于是给改成了上面这个样子:

<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>

我的批改根据是:

  1. throttle 办法返回的是一个匿名函数,这个函数正好充当 input 事件的回调函数
  2. input 事件回调函数中的 this 指向的是 inputEle
  3. 匿名函数中将 this 绑定给了 fun 参数,而理论应用中传入的是 changeOutputVal 办法
  4. 所以 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

~

~

~ 本文完,感激浏览!

~

学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂!

我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教!

你来,怀揣冀望,我有墨香相迎!你归,无论得失,唯以余韵相赠!

常识与技能并重,内力和外功兼修,实践和实际两手都要抓、两手都要硬!

正文完
 0