一.setInterval 与 setTimeout区别:
`setInterval('func1()',1000)`
在1秒后执行该函数;
idTime = setInterval('func2()',1000)
clearInterval(idTime);
每秒都执行一次,直到调用clearInterval后为结束。
两个函数都为全局函数,在该函数内部如果调用this指针,该指针指向的是window对象!
二.如何用setInterval来调用类的方法呢?
为什么会存在这种情况?
在调用setInterval(func(),1000)
的时,大多是在某个函数体类。在该函数里面,会有上下文关联,比如:变量,或者func() 方法本身就需要调用类的某些属性。
有点绕,是时候上例子了
function SimpleDialog(props) {
AbstractDialog.call(this, props);
}
inheritPrototype(SimpleDialog, AbstractDialog);
SimpleDialog.prototype.timeShow = function () {
this.onload();
var dialog = document.getElementById('divDialog');
dialog.style.opacity = 1;
var changeOpacity = function () {
console.log('last');
var opacity = dialog.style.opacity;
dialog.style.opacity = opacity - 0.1;
if (Number(dialog.style.opacity) === Number(0)) {
this.closeDialog();
clearInterval(idTime);
}
};
var THIS = this;
// 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
var idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
console.log(idTime);
dialog.onmouseenter = function (event) {
document.getElementById('divDialog').style.opacity = 1;
event.stopPropagation();
clearInterval(idTime);
console.log('onmouseenter');
};
dialog.onmouseleave = function (e) {
clearInterval(idTime);
idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
// this.idTime如果声明为内部对象会存在问题
};
};
以上为部分关键代码示例:
SimpleDialog类继承于AbstractorDialog,其中timeShow()方法为自定义方法,目的是实现弹出对话框的渐进消失效果。
主要实现了如下功能
- 对话框弹出后,渐进透明,直到关闭
- 当鼠标移动到对话框上时 触发onmouseenter事件,重置对话框透明属性为1,并停止渐进效果
- 当鼠标移除对话框后,触发onmouseout事件,对话继续渐进透明,直到关闭。
(有关对话框的设计,改天再开个口)
很容易想到第一步,如何设置变化?
查到有setInterval(func1(),1000)
可以设置为每秒执行,1000以毫秒为单位。
第二步,如何监听变化,执行到某一步的时候结束程序?
自然想到这部监听要在func1()里面来做。
针对这里的需求来第一版本:
function changeOpacity() {
console.log('last');
var opacity = document.getElementById('divDialog').style.opacity;
document.getElementById('divDialog').style.opacity = opacity - 0.1;
if (Number(document.getElementById('divDialog').style.opacity) === Number(0)) {
closeDialog();
clearInterval(idTime);
}
};
var idTime;
function closeDialog() {
var props = {
'title': '日期格式有误,请重新填写'
};
var diglog = new AbstractDialog(props);
diglog.closeDialog();
}
SimpleDialog.prototype.timeShow = function() {
this.onload();
var dialog = document.getElementById('divDialog');
dialog.style.opacity = 1;
// 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
idTime = setInterval('changeOpacity()', 100);
console.log(idTime);
dialog.onmouseenter = function(event) {
document.getElementById('divDialog').style.opacity = 1;
event.stopPropagation();
clearInterval(idTime);
console.log('onmouseenter');
};
dialog.onmouseleave = function(e) {
clearInterval(idTime);
idTime = setInterval('changeOpacity()', 100);
// this.idTime如果声明为内部对象会存在问题
};
};
这个代码不痛快的地方在哪里呢?
首先在SimpleDialog.prototype.timeShow
为Dialog的初始化方法,在里面调用了基类的onload初始化函数,并在设定了onmousenter与onmouseleave两个事件。事件中添加setInterval 方法!
第二定义两个全局函数 一个为closeDialog() 调用基类的closeDialog()来移动对话框
第三,定义setInterval的回调函数 changeOpacity
第四,为了使changOpacity 在 opactiy==0时, 调用clearInterval,需将句柄idTime设置为全局变量
第二点与第四点简直不能忍~这里回答了为什么需在类内调用windows的全局方法。
首先查到setInterval()在类中调用的如下方法:
function Person(name){
this.name=name;
var f=function(){alert('My name is '+this.name)};
// setTimeout(f,50); //错误
var THIS=this;
setTimeout(function(){f.apply(THIS)},50); //正确,通用
setTimeout(function(){f.call(THIS)},50); //正确,通用
}
new Person('Jack');
这里的回调函数f实质上是一个闭包,但能满足作为setInterval回调函数的需求!其次闭包能截取上下文的变量,这可以解决idTime作为全局变量的问题,(闭包的实质是一个全局对象,所有的该闭包函数,都指向这个对象)。
其次,调用call函数将this 指向Dialog。那么就可以在闭包中调用this.closeDialog()来关闭窗体了
var THIS=this;
//如果直接写成f.apply(this)},这个this将会指向window对象,而window对象没有closeDialog功能~。
setTimeout(function(){f.apply(THIS)},50); //正确,通用
于是有了下代码
SimpleDialog.prototype.timeShow = function () {
this.onload();
var dialog = document.getElementById('divDialog');
dialog.style.opacity = 1;
var changeOpacity = function () {
var opacity = dialog.style.opacity;
dialog.style.opacity = opacity - 0.1;
if (Number(dialog.style.opacity) === Number(0)) {
this.closeDialog();
clearInterval(idTime);
}
};
var THIS = this;
// 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
var idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
console.log(idTime);
dialog.onmouseenter = function (event) {
document.getElementById('divDialog').style.opacity = 1;
event.stopPropagation();
clearInterval(idTime);
console.log('onmouseenter');
};
dialog.onmouseleave = function (e) {
clearInterval(idTime);
idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
// this.idTime如果声明为内部对象会存在问题
};
三 渐进消失效果 只是修改了opacity属性 就不表了
实现效果如下