最近看了一段代码,感到疑惑。
有一个Player类,有start、next等方法。
请问:
1.
this.interval=setInterval(function () {_this.next();},this.timeout)与this.interval=setInterval(this.next,this.timeout)的本质区别是什么?(这句代码在第30行,我做了标记)2.
第2句代码为什么不能正确执行,求解释!3.
setInterval的第一个参数使用function () {}把_this.next()包含其中,是不是为了突出面向对象思想对于方法的特性?
源代码如下://这是一个图片轮播器
function Player(buttons,scrollContent,imageHeight,hoverClass,timeout) {     //这里先暂且不管hoverClass
hoverClass=hoverClass || 'hover';
timeout=timeout || 3000;
this.buttons=buttons;
this.scrollContent=scrollContent;
this.hoverClass=hoverClass;
this.timeout=timeout;
this.imageHeight=imageHeight;

this.curItem=buttons[0];
var _this=this;
for (var i=0;i<this.buttons.length;i++) {
this.buttons[i].onmouseover=function () {
_this.stop();
_this.invoke(this.index);
};
this.buttons[i].onmouseout=function () {
_this.start();
};
this.buttons[i].index=i;
}
this.invoke(0);
}Player.prototype={
start:function () {
var _this=this;
this.stop();
this.interval=setInterval(function () {             /*********就是这里**********/
_this.next();
},this.timeout);
},
stop:function () {
clearInterval(this.interval);
},
invoke:function (n) {//具体显示哪一帧

this.curItem=this.buttons[n];


//this.scrollContent.style.top=-n*this.imageHeight+"px";
var top=parseInt(this.scrollContent.style.top) || 0;
this.animateIterval && this.animateIterval();
this.animateIterval=animate(this.scrollContent,{
top:top
},{top:(-n*this.imageHeight)-top},1000,Tween.Quad.easeInOut);

//先将所有按钮样式恢复
this.recoverButtonsClass();
this.curItem.className=this.hoverClass;


},
next:function () {
//this.curItem.index//curItem当前的那一帧
var nextIndex=this.curItem.index+1;
if (nextIndex>=this.buttons.length) {
nextIndex=0;
}
this.invoke(nextIndex);
},
recoverButtonsClass:function () {//将所有按钮样式恢复
for (var i=0;i<this.buttons.length;i++) {
this.buttons[i].className='';
}
}
};
window.onload=function () {
var btns=getByClass('buttons')[0].getElementsByTagName('li');
var scrollContent=getByClass('scrollContent')[0];
var player=new Player(btns,scrollContent,150,undefined,1000);
player.start();//开始播放
};

解决方案 »

  1.   

    this.next     内部 this-->window ...
      

  2.   

    但是用_this.next也会出现这个问题
      

  3.   

    先回答第一个问题,看例子var b = "111";
    function Test(){    
         var _this = this;
         this.b = "333";
         this.fn = function(){
         alert(this.b)
         }    
         this.time1 = setTimeout(this.fn, 1000);
        
         this.time2 = setTimeout(function(){
         _this.fn()
         }, 1000);
        
        
         }
         var a = new Test();
    第一个定时器弹出111,第二个弹出333首先我们要知道,执行函数的时候上下文的绑定,看下面例子
    function fn(){
       this.b = "123"
    }
    1,fn();//这时,this绑定到fn的上一级作用域上下文,即window
    2,new fn();//this绑定到fn本身的上下文。由此可知,当普通执行函数的时候,this会绑定到函数本身上一级作用域的上下文,而new的时候,this才会绑定到本身的上下文。我们回头看定时器,首先,定时器里面的函数的作用域是与上一级作用域是同级的,也就是相同的,所以
    function test(){
       setTimeout(function ff(){},1000);
    }
    ff函数的作用域也就是test的作用域。我们继续分析定时器1:this.time1 = setTimeout(this.fn, 1000);
    可以看成
    this.time1 = setTimeout(function (){
      alert(this.b);
    },1000);
    由上面例子可以知道,普通执行的时候this会绑定到函数上一级作用域的上下文,在这个计时器中,this就绑定到window中,所以this.b ==>window.b==>var b = "111"定时器2:this.time2 = setTimeout(function(){
         _this.fn()
        }, 1000);
    可以看成
    this.time2 = setTimeout(function (){
         function f(){
              alert(this.b)
         }
         f();
    },1000);
    这时f()是普通调用函数,所以this就绑定到f的上一级作用域的上下文,即Test的上下文,this.b ==> Test中的this.b = "333";
      

  4.   

    next:function () {
            //this.curItem.index//curItem当前的那一帧
            var nextIndex=this.curItem.index+1;
            if (nextIndex>=this.buttons.length) {
                nextIndex=0;
            }
            this.invoke(nextIndex);
        }
    有刚才第一个问题的分析,可知第三个问题就是为了next里面的this绑定到Player类的上下文this.curItem,this.buttons这些就能正常访问到了
      

  5.   

    setInterval()是一个全局方法,完整的调用方法是window.setInterval(),所以this.interval=setInterval(this.next,this.timeout)这样写里面的this指的是window,而并没有window.next()这个方法,所以会出错。而this.interval=setInterval(function () {_this.next();},this.timeout)这样写就大不相同了,里边的_this是Player.prototype里面的this
      

  6.   

    <<scope>> this指针的作用域
      

  7.   

    更正一下~
    this.interval=setInterval(this.next,this.timeout)这里的this不是指向window的 ,它就是指向Pleyer的上下文,只不过是因为this.next函数里面的this.curItem,这里的this指向了window,所以报错
      

  8.   

    也就是说当定时器的第一个参数为function () { _this.next(); }时,就相当于new ...(),是这个意思吗?
      

  9.   

    也就是说当定时器的第一个参数为function () { _this.next(); }时,就相当于new ...(),是这个意思吗?
      

  10.   

    重点是记住2个要点
    普通fn()的时候this绑定的是上一级作用域的上下文,
    new fn()的时候this绑定的是本函数作用域的上下文
      

  11.   

    我还是很不明白,第二个定时器中f()的作用域应该和包含他的函数的作用域一样吧,不是window吗?
      

  12.   

    第二个是指
    this.time2 = setTimeout(function ff(){
      function f(){
      alert(this.b)
      }
      f();
    },1000);
    因为ff是普通调用所以ff里面的this指向的是Test的this,f()也是普通调用,所以f()里面的this指向的是ff的this,由上面条件可知f()的this指向的是Test的this
    同时var a = new Test();所以Test里面的this指向的是Test本身的上下文
    就可以推出f()的this指向的就是Test本身的上下文
      

  13.   

    f()普通调用得知  f();this ==> ff();thisff()普通调用得知 ff();this ==>Test(); thisTest()是new 调用得知 Test();this ==> Test(); this所以f();this ==> Test();this
      

  14.   

    我的理解是:第一个定时器也是普通调用,那this也就应该指向player对象。
      

  15.   

    好像有点懂了,使用setInterval(_this.next,_this.timeOut),是把next的方法体传个了定时器,当调用时,this指向了window,而window没有curItem属性,所以报错,是这样理解吗?
      

  16.   

    直接使用 this 代表 window  如果在一个  对象中 就代表该对象   this的鸟语就是 这个,  本身的意思
      

  17.   

    this.time1 = setTimeout(function (){
      alert(this.b);
    },1000);
    函数上一级作用域的上下文不是test吗?
      

  18.   

    感觉五楼说的对,听不懂liangws
      

  19.   

    this.interval=setInterval(this.next,this.timeout)肯定是没错的。它能找到this.next,只是里面的this.next里面的this.curItem找不到
    var b = "111";
    function Test(){            
                var _this = this;
                this.b = "333";
                this.fn = function(){
                    alert(this.b)
                }            
                this.time1 = setTimeout(this.fn, 1000);
                
                this.time2 = setTimeout(function(){
                    _this.fn()
                }, 1000);
                
                
            }
            var a = new Test();这个例子不是很清楚么,
    如果            this.time1 = setTimeout(this.fn, 1000);这里的this.fn的this是window的话,就根本执行不了
      

  20.   

    <script>
    var b = "111";
    function Test(){            
                var _this = this;
                this.b = "333";
                this.fn = function(){
                    alert(this.b)
                }            
                this.time1 = window.setTimeout(this.fn, 1000);
                
                this.time2 = window.setTimeout(function(){
                    _this.fn()
                }, 1000);
                
                
            }
            var a = new Test();
    </script>这样执行没有问题。<script>
    var b = "111";
    function Test(){            
                var _this = this;
                this.b = "333";
                this.fn = function(){
                    alert(this.b)
                }            
                this.time1 = this.setTimeout(this.fn, 1000);
                
                this.time2 = this.setTimeout(function(){
                    _this.fn()
                }, 1000);
                
                
            }
            var a = new Test();
    </script>
    这样就可以了,所以五楼的说法应该是正确的
      

  21.   

    setInterval(this.next,this.timeout)中的this是指的Test类,调试的时候并不是在这一步报错的,而是在next方法中没有找到curItem属性