最近看了一段代码,感到疑惑。
有一个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();//开始播放
};
有一个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();//开始播放
};
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";
//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这些就能正常访问到了
this.interval=setInterval(this.next,this.timeout)这里的this不是指向window的 ,它就是指向Pleyer的上下文,只不过是因为this.next函数里面的this.curItem,这里的this指向了window,所以报错
普通fn()的时候this绑定的是上一级作用域的上下文,
new fn()的时候this绑定的是本函数作用域的上下文
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本身的上下文
alert(this.b);
},1000);
函数上一级作用域的上下文不是test吗?
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的话,就根本执行不了
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>
这样就可以了,所以五楼的说法应该是正确的