想显示导入文件进度,js实现了一个导入耗费时间的效果,但是想将其封装成面向对象的,可是封装之后没有正常运行,js 面向对象能力不够啊,不知道代码是啥原因,setinterval没有间隔时间运行,只运行了一次,请高手指导一下原因,谢谢啦!
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>新增属性值</title> <script type="text/javascript" src="jquery-1.10.2.min.js"></script> </head> <body> <div id="importInfo"></div> <input type="button" onclick="inportProcesser.Start()" value="开始"> <input type="button" onclick="inportProcesser.Close()" value="结束"> <script> function Progresser(intervalms, intervalHandle) { this.intervalMs = intervalms; this. totalIntervalMs = 0; this. timer=null; this.Oninterval = intervalHandle; } Progresser.prototype = { constructor: Progresser, Start: function () { //console.log("Start totalIntervalMs:" + this.totalIntervalMs); this.timer = setInterval( this.IntervalHandle() , this.intervalMs); //console.log("Start timer:" + this.timer); }, Close: function () { //console.log("Close totalIntervalMs:" + this.totalIntervalMs); if (this.timer != null) { //console.log("Close timer:clearInterval pre" + this.timer); clearInterval(this.timer); //console.log("Close timer:clearInterval next" + this.timer); } this.totalIntervalMs = 0; } , IntervalHandle: function () { this.totalIntervalMs += this.intervalMs ; //console.log("IntervalHandle totalIntervalMs:" + this.totalIntervalMs); this.Oninterval(this.totalIntervalMs); //console.log("IntervalHandle timer:" + this.timer); } } var inportProcesser = new Progresser(500, importing2); function importing2(totalIntervalMs) { var second = (totalIntervalMs / 1000.0).toFixed(1); console.log("seconds:" + second + "s.."); } </script> </body> </html>
Start: function () { //console.log("Start totalIntervalMs:" + this.totalIntervalMs); this.timer = setInterval( () => { this.IntervalHandle(); }, this.intervalMs); //console.log("Start timer:" + this.timer); },
这里改成这样就可以了
ok,没问题了,多谢!
如果能阐释一下原理的话,就完美了!!!
@摆脱菜鸟:
setInterval 的第一个参数应该是个 function,所以这里
this.timer = setInterval( this.IntervalHandle() , this.intervalMs);
不应该带括号,带了括号这里就变成 this.IntervalHandle 函数的返回值了,就要写成这样:
this.timer = setInterval( this.IntervalHandle , this.intervalMs);
但是这样又会出现另外一个作用域的问题,setInterval 调用的函数内部 this 指向的是 window,
this.Oninterval(this.totalIntervalMs);
代码运行到这里就会报错,因为 window 对象上面没有 Oninterval 这个方法,代码我是用的箭头函数,改造成兼容 ES5 的就像这样:
Start: function () { //console.log("Start totalIntervalMs:" + this.totalIntervalMs); var self = this; this.timer = setInterval(function() { self.IntervalHandle(); }, this.intervalMs); //console.log("Start timer:" + this.timer); },
这样解释希望能明白?
@by.Genesis:
上面的代码运行有问题了,啥原因?箭头函数方式firfox中运行没问题,但是ie中不能正常运行。
你改造后的代码,都不能运行了。
楼下兄弟的代码都能兼容运行,但是声明全局变量破坏了封装性啊,如何破?
@摆脱菜鸟:
箭头函数是ES6的写法,老浏览器不兼容,我修改后的代码我是经过测试了的没有问题啊
@by.Genesis:
确实不能执行有问题啊,其他方法没改动吗?
@摆脱菜鸟:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>新增属性值</title> </head> <body> <div id="importInfo"></div> <input type="button" onclick="inportProcesser.Start()" value="开始"> <input type="button" onclick="inportProcesser.Close()" value="结束"> <script> function Progresser(intervalms, intervalHandle) { this.intervalMs = intervalms; this. totalIntervalMs = 0; this. timer=null; this.Oninterval = intervalHandle; } Progresser.prototype = { constructor: Progresser, Start: function () { var self = this; //console.log("Start totalIntervalMs:" + this.totalIntervalMs); this.timer = setInterval( function() { self.IntervalHandle(); } , this.intervalMs); //console.log("Start timer:" + this.timer); }, Close: function () { //console.log("Close totalIntervalMs:" + this.totalIntervalMs); if (this.timer != null) { //console.log("Close timer:clearInterval pre" + this.timer); clearInterval(this.timer); //console.log("Close timer:clearInterval next" + this.timer); } this.totalIntervalMs = 0; } , IntervalHandle: function () { this.totalIntervalMs += this.intervalMs ; //console.log("IntervalHandle totalIntervalMs:" + this.totalIntervalMs); this.Oninterval(this.totalIntervalMs); //console.log("IntervalHandle timer:" + this.timer); } } var inportProcesser = new Progresser(500, importing2); function importing2(totalIntervalMs) { var second = (totalIntervalMs / 1000.0).toFixed(1); console.log("seconds:" + second + "s.."); } </script> </body> </html>
我把全部代码贴上来
@by.Genesis:
没有问题,我的错误,我有个地方改错了,谢了大神!!
楼上的解答是正确的,但这是ES6的写法,其实你的问题是一个“js闭包”的问题而已。
解决办法可以先声明一个全局变量
步骤一
var this_ = null;
步骤二
Start: function () {
//console.log("Start totalIntervalMs:" + this.totalIntervalMs);
this_ = this;
this.timer = setInterval( this.IntervalHandle , this.intervalMs);
/****************************
说明,问题是你原来是this.IntervalHandle()调用的,但实际上应该是this.IntervalHandle,不需要();
问题又来了,this.IntervalHandle在setInterval里面单独调用的话那么this.IntervalHandle函数的
this指向的就是windos对象了。因为setInterval是全局函数。
***********************************************/
//console.log("Start timer:" + this.timer);
},
步骤三
IntervalHandle: function () {
this_.totalIntervalMs += this_.intervalMs ;
//console.log("IntervalHandle totalIntervalMs:" + this.totalIntervalMs);
this_.Oninterval(this_.totalIntervalMs);
//console.log("IntervalHandle timer:" + this.timer);
}
谢谢,没太看明白,对于闭包一直没理解,js简单的能写,深入的话,尤其是封装的,看着一头雾水啊!
有时间我还是要好好看看那本js高级程序设计,多研究一下开源代码!