JavaScript学习总结之匿名函数的this指向问题

前言

JavaScript中的this指向问题对于web前端入行不深的人来讲是个比较复杂的问题。特写此文章来记录今天遇到的关于匿名函数中this指向问题的思考和感悟。前端

问题复现

今天在研究函数防抖场景时看到以下代码:web

function debounce(fn, delay) {
        var timer; // 维护一个 timer
        return function () {
            var _this = this; // 取debounce执行做用域的this
            var args = arguments;
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                fn.apply(_this, args); // 用apply指向调用debounce的对象,至关于_this.fn(args);
            }, delay);
        };
    }

其中有一段代码是 var _this = this 这段代码出如今由return返回的匿名函数中,这个时候我就有些懵逼了,由于根据我匮乏的js知识,这里的this应该是指向全局做用域才对,为何能像注释那样指向debounce执行时的做用域呢?感受以下所写是否更加合理呢?(事实证实这么写确定是不对的)闭包

function debounce(fn, delay) {
    var timer
    var _this = this
    return function() {
    ...
    }
}

因而我打算用代码来实测这里的 debounce执行做用域中的this到底指的是什么,它会变化吗?仍是根据个人理解只要是像相似的匿名函数其中的this都是指向全局的呢?app

因而我写下以下代码(关键部分):
body部分新增一个button标签函数

`<button>我是button</button>`

script标签内部代码以下:this

//函数防抖
    function debounce(fn, delay) {
        var timer; // 维护一个 timer
        return function () {
            var _this = this; // 取debounce执行做用域的this
            var args = arguments;
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                fn.apply(_this, args); // 用apply指向调用debounce的对象,至关于_this.fn(args);
            }, delay);
        };
    }
    

    var btn = document.getElementsByTagName('button')[0]

    btn.onclick= debounce(function() {
        console.log(this)
    }, 1000)

点击按钮,看看控制台输出this究竟是谁,按照我以前的理解输出的this应该是window全局对象才对
console.pngspa

出乎意料,这里的this输出的是button元素,因而我再在上述脚本中新增一个事件绑定:code

window.onclick = debounce(function() {
        console.log(this)
    }, 1000)

点击页面空白处输入以下:
console2.png
此次输出的就是window了! 看来这里的this实际是跟debounce函数所返回函数的实际调用者有关,第一次控制台输出的是button元素,由于是经过button元素来调用该返回函数,第二次调用者就是widnow,举这段btn.onclick = dobounce(function() {console.log(this)}, 1000) 代码的例子:对象

  1. 页面初始化完毕后,执行脚本代码, debounce函数接收一个具体函数(将其命名为fn好了)和一个时间间隔参数(intervcal)
  2. 进到debounce代码内部,return 一个匿名函数,并赋给btn.onclick,实际上就是事件绑定
  3. 因此说当我点击button的时候,btn.onclick的执行代码是这样的:
btn.onclick = function() {
    var _this = this; // 取debounce执行做用域的this
    var args = arguments;
    if (timer) {
        clearTimeout(timer);
    }
    //由于闭包的存在timer仍是取的debounce中的timer
    timer = setTimeout(function () {
        fn.apply(_this, args); // 用apply指向调用debounce的对象,至关于_this.fn(args);
    }, delay);
}

那么这里的this指向的就是button元素了,为何呢,emmm写了太多了,打算专门再写一篇总结来延伸this的指向问题,今天的总结到此结束!blog

相关文章
相关标签/搜索