请问为什么autoPlay方法里的this指向了window??

function Slider(selector) {
        this.container = MyLib.getObj.getElem(selector);
        this.imgs = MyLib.getObj.getAllElem(".c-slider__item", this.container);
        this.btns = MyLib.getObj.getAllElem(".c-pointer__btn", this.container);
        this.cur = null;
        this.init();
    }
    
    
    Slider.prototype.init=function(){
        var _this=this;
        this.timer=setInterval(_this.autoPlay,3000);
        this.hover();
        this.clickBtn();
    }
    
    Slider.prototype.clickBtn=function(){
        for (var i = 0; i < this.btns.length; i++) {
            this.btns[i].index = i;
            var _this = this;
            this.btns[i].onclick = function () {
                _this.cur = this.index;
                _this.switchImg(_this.cur);
            }
        }
    }
    
    Slider.prototype.hover=function(){
        var _this=this;
        this.container.onmouseenter=function(){
           clearInterval(_this.timer);
        };
        this.container.onmouseleave=function(){
            _this.timer=setInterval(_this.autoPlay,3000);
        }
    }

    Slider.prototype.switchImg = function () {
        for (var i = 0; i < this.btns.length; i++) {
            var _this = this;
            MyLib.classMether.removeClass(_this.btns[i], "c-pointer__btn--active");
        };
        MyLib.classMether.addClass(_this.btns[_this.cur], "c-pointer__btn--active");
        for (var j = 0; j < this.imgs.length; i++) {
            this.animateImg(this.imgs[i],0);
        }
        this.animateImg(this.imgs[this.cur],100);
    }

    Slider.prototype.animateImg = function (elem, target) {
        var timer =setInterval(function () {
            var curopacity = MyLib.getStyle(elem, "opacity");
            var speed = 0;
            if (curopacity > target) {
                speed = -5;
            } else if (curopacity < target) {
                speed = 5;
            };
            if (curopacity == target) {
                clearInterval(this.timer);
            } else {
                curopacity += 5;
            };
            elem.style.opacity=curopacity/100;
            elem.sytle.filter='alpha(curpacity:'+inopacity+')';
        }, 30);

    }
    
    Slider.prototype.autoPlay=function(){
        console.log(this);
        if(this.cur==this.imgs.length-1){
            this.cur=0;
        }else{
            this.cur++;
        };
        this.switchImg();
    }

    new Slider();
    
     

只在这几个方法里调用过autoPlay方法:

    
    Slider.prototype.init=function(){
    var _this=this;
    this.timer=setInterval(_this.autoPlay,3000);
    this.hover();
    this.clickBtn();
}

Slider.prototype.hover=function(){
    var _this=this;
    this.container.onmouseenter=function(){
       clearInterval(_this.timer);
    };
    this.container.onmouseleave=function(){
        _this.timer=setInterval(_this.autoPlay,3000);
    }
}

Slider.prototype.autoPlay=function(){
    console.log(this);
    if(this.cur==this.imgs.length-1){
        this.cur=0;
    }else{
        this.cur++;
    };
    this.switchImg();
}

为什么在autoPlay里this会变成了window???什么时候变的?在哪里变的?怎么变的?想了很久还是想不明白...

阅读 3.4k
4 个回答

clipboard.png

你能理解这个吗?它们的是同一个原因导致的。就是函数就是一个独立对象,哪怕它的定义是在一个对象的属性。里面的this也只由调用位置的绑定情况决定,与定义位置无关。

你的实例里面,autoPlay的调用位置不是你写的setInterval这里,而是setInterval内部。你只是把autoPlay这个函数作为参数传给了setInterval而已。传参的时候相当于图片里面的var d = a.c;一样,这时候只把函数传递过去了,此时的函数是未被绑定的。

setInterval(_this.autoPlay.bind(_this),3000);

由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. 这会导致,这些代码中包含的 this 关键字会指向 window (或全局)对象,这和所期望的this的值是不一样的

https://developer.mozilla.org...

setInterval直属于window,setInterval去执行_this.autoPlay之后,autoPlay里面的this就变成了setInterval。你可以用call() 或者 apply()强制函数调用的上下文环境

_this.timer=setInterval(_this.autoPlay.call(_this),3000);//网友指出这样写是错了,autoPlay会被立即执行,经过测试确实被立即执行了
/** 修正:包一层 **/
setInterval(runAutoPlay,3000);
var runAutoPlay = function() {
        objS.autoPlay();
    };
var objS = new Slider();
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
1 篇内容引用
推荐问题
logo
Microsoft
子站问答
访问
宣传栏