关于setTimeout的问题

具体问题就是setTimeout里面执行方法本身的时候,直接写方法名会报错,也许是我搜索的方式不对,没有搜到相关答案。
this.timer = setTimeout(self.change, this.s); 这样写会报错
写这个是为了实现字体不停变色。

function ChangeColor(id,arr,s) {
    this.id = id;
    this.arr = arr;
    this.s = s;
    this.i = 0;
    this.timer = null;
}

ChangeColor.prototype = {
    change : function () {
        let self = this;
        if (this.arr[this.i]) {
            $(this.id).css('color', this.arr[this.i]);
        }

        this.i === 0 ? this.i++ : this.i = 0;
        // this.timer = setTimeout(self.change, this.s);
        this.timer = setTimeout(function () {
            // console.log(self);
            self.change();
        }, this.s);
    }
};

let txt = new ChangeColor('.txt',['#fff','#000'],200);
txt.change();

谢谢

阅读 2.7k
5 个回答
//修改
this.timer = setTimeout(this.change.bind(this), this.s);

初始化运行正常,定时器触发后,change函数作为setTimeout的回调函数,此时this指向了window,执行this.arr[this.i]报错.

最后,函数调用是txt.change(),不是txt.changeColor()

你这不是递归了吗。
递归的话没有边界,跑一会内存会蹦。
在change 函数外面用定时器调用

楼上说的是对的,这是关于this的指向的问题,要搞清楚this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件,this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。具体可以看下我总结的一篇读书笔记JavaScript基础系列--打败this

第一次直接调用txt.change()的时候,this指向txt这个对象,所以self也指向txt这个对象,所以初始化的时候运行正常。
setTimeout的回调的调用位置始终是全局作用域,所以回调里面的this是指向全局对象---浏览器里是window对象,现在你把self.change作为setTimeout的回调,那么定时器到点触发后,回调self.change里的this就指向window了,而window是没有arr,i这些属性的,所以执行到if (this.arr[this.i])时会报错:Cannot read property 'undefined' of undefined

如果仅仅是需要达到这个效果,不一定用你的方法,你可以采用循环定时器触发。
然后在相应处理中去操作具体的对象属性值,达到效果。

楼上说的是对的,这是关于this的指向的问题,要搞清楚this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件,this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。具体可以看下我总结的一篇读书笔记JavaScript基础系列--打败this

txt.change()

第一次直接调用的时候,this指向txt这个对象,所以self也指向txt这个对象,所以初始化的时候运行正常。
setTimeout的回调的调用位置始终是全局作用域,所以回调里面的this是指向全局对象---浏览器里是window对象,现在你把self.change作为setTimeout的回调,那么定时器到点触发后,回调self.change里的this就指向window了,而window是没有arr,i这些属性的,所以执行到if (this.arr[this.i])时会报错:Cannot read property 'undefined' of undefined

推荐问题
宣传栏