发新贴  快速回复

在js中不是只会保存一个变量timer的吗?如果点击两次btn01,第二次点击之后会把,第一次的赋值清除才对额,怎么会出现函数叠加的现象呢?

Shark
2017-06-25 23:57

<style>
    #div1{width:100px;height:100px;background:red;position:relative;top:50px;left:30px;}
</style>
</head>

<body>
<input type="button" value="按钮" id="btn01">
<div id="div1"></div>
</body>
<script>
    var oBtn=document.getElementById("btn01");
    var oDiv=document.getElementById("div1");
    var timer=null;
    oBtn.err=function(){
        //alert(getStyle(oDiv,"left"))
        //oDiv.style.left=parseInt(getStyle(oDiv,"left"))+10+"px"
        
            
            timer = setInterval(function(){
                var speed=oDiv.style.left=parseInt(getStyle(oDiv,"left"))+10
                if(speed>800){speed=800};
                oDiv.style.left=speed+"px";
            
            if(speed==800){
                clearInterval(timer);
                alert(speed);
            }
            
            },30)
            
        
    }
    function getStyle(obj,attr){ return obj.currentStyle?obj.currentStyle[attr]:getComputedStyle(obj)[attr];}
</script>
</html>
 

本帖内容针对以下视频发布:

1-定时器管理-开关设置
 
妙味用户762088

是只能保存一个变量timer,你的问题出现在这里:虽然第二次点击的时候timer变量的值改变了,但是,在第一次点击之后的定时器并没有关闭,后来点击的时候又开启了一个定时器,并把它赋值给timer。所以会出现定时器叠加。所以要在点击之后增加一个clearIntervel事件,来清空在运行的定时器,这样就不会产生叠加。

希望能帮到你~

2017-06-26 00:14  回复本帖
Shark

妙味用户762088 2017-06-26 00:14发表的内容:

是只能保存一个变量timer,你的问题出现在这里:虽然第二次点击的时候timer变量的值改变了,但是,在第一次点击之后的定时器并没有关闭,后来点击的时候又开启了一个定时器,并把它赋值给timer。所以会出现定时器叠加。所以要在点击之后增加一个clearIntervel事件,来清空在运行的定时器,这样就不会产生叠加。

希望能帮到你~

还是有点不明白,第一次的定时器不是被保存在timer里的应该不止是一个值的意思吧,不然后面在使用clearInterval(timer);就没意义了,应该是保存的是一个定时器的意思吧,然后使用了clearInterval()才能把timer保存的定时器清除?

2017-06-26 09:38  回复本帖
 
leo

你说“第二次点击之后会把,第一次的赋值清除才对额”——但从你上面的代码来看,你只是在脑海里 “希望” 第二次点击清除,但你代码中却没有清除的命令,你只是设置了到达目标点以后,才清除命令。

想第二次点击之后把第一次清除,要么做个第一次、第二次……的管理,要么就在每次执行定时器前,清除定时器,别只是想,要体现在代码中哈~

2017-06-26 23:22  回复本帖
Shark

leo 2017-06-26 23:22发表的内容:

你说“第二次点击之后会把,第一次的赋值清除才对额”——但从你上面的代码来看,你只是在脑海里 “希望” 第二次点击清除,但你代码中却没有清除的命令,你只是设置了到达目标点以后,才清除命令。

想第二次点击之后把第一次清除,要么做个第一次、第二次……的管理,要么就在每次执行定时器前,清除定时器,别只是想,要体现在代码中哈~

你没理解我意思,我是没有写清除 但是,一个变量timer只能保存一个值啊,所以我认为不需要写清除命令,第二次的点击事件产生的值,会把第一次点击时产生的值覆盖掉,最终只会保留一个定时器这个意思

2017-06-26 23:53  回复本帖
 
leo

定时器的作用可不像是定义一个数字那样简单,比如 var n = 1;

你把 n 修改成了 2,那 n 以后就是 2 了。

定时器是要 “干活” 的,每次你调用一个定时器,就相当于让它延时执行某个命令(在你这段代码中就是让 DIV 往前跑……),当你再次点击时,上次定时器你又没关闭(休想以变量覆盖的方式 “自动” 让上一个定时器关闭),所以下一个定时器里的命令 + 上一个定时器里的命令,就相当于数字累加给 DIV ,让它更快的往前跑……

想让定时器乖乖听话,你必须要严格监控定时器的每一个举动,要执行下一个之前,必须关闭上一个,不然浏览器就被你 “整惨了”。

 

2017-06-27 17:28  回复本帖
 
leo

而严格监控定时器的办法,是给一个变量名称,上面的代码中你设置了一个 timer 作为定时器管理的名字。有了这个名字,只是给你一个可以 “监管” 定时器的方法,如果你不在启动下一次定时器前把上一个定时器关闭(也就是利用 timer 这个名称去清除定时器)的话,嘿嘿,JS 就会为你在后台默默开第二个定时器……你敢再点一下,JS 就会默默开第三个、第四个……直到你的浏览器崩溃。

指望用变量覆盖的方式关闭定时器?除非你重新发明 JS 语言规则哈~~

2017-06-27 17:32  回复本帖
 
leo

简单总结:想用变量值修改的方式清除定时器……除非重新发明 JS 规则、并且让浏览器都支持这种特性,否则没戏哈~

2017-06-27 17:38  回复本帖
Shark

leo 2017-06-27 17:28发表的内容:

定时器的作用可不像是定义一个数字那样简单,比如 var n = 1;

你把 n 修改成了 2,那 n 以后就是 2 了。

定时器是要 “干活” 的,每次你调用一个定时器,就相当于让它延时执行某个命令(在你这段代码中就是让 DIV 往前跑……),当你再次点击时,上次定时器你又没关闭(休想以变量覆盖的方式 “自动” 让上一个定时器关闭),所以下一个定时器里的命令 + 上一个定时器里的命令,就相当于数字累加给 DIV ,让它更快的往前跑……

想让定时器乖乖听话,你必须要严格监控定时器的每一个举动,要执行下一个之前,必须关闭上一个,不然浏览器就被你 “整惨了”。

 

setInterval()应该也是属于js原生的一个方法把,他的实质是和函数差不多的吧,要是把一个函数赋值给了变量,第二次变量重新赋值一个函数,那也应该会把上一个函数覆盖掉啊

2017-06-27 17:58  回复本帖
 
leo

Shark 2017-06-27 17:58发表的内容:

setInterval()应该也是属于js原生的一个方法把,他的实质是和函数差不多的吧,要是把一个函数赋值给了变量,第二次变量重新赋值一个函数,那也应该会把上一个函数覆盖掉啊

定时器的特性是:你开启了想停下来?除非用清除定时器的方法(clear...)。想用变量覆盖的方式是不行的。

关键点是:函数已经执行了……

相当于你把 A 函数执行了,然后通过某种操作,然后让 A 函数变成的 A1 函数,但问题是:A 函数已经执行了……
2017-12-29 14:51  回复本帖
Shark

leo 2017-12-29 14:51发表的内容:

定时器的特性是:你开启了想停下来?除非用清除定时器的方法(clear...)。想用变量覆盖的方式是不行的。

关键点是:函数已经执行了……

相当于你把 A 函数执行了,然后通过某种操作,然后让 A 函数变成的 A1 函数,但问题是:A 函数已经执行了……
嗯,
问题1:.setinterval作为window下的公共方法执行完成之后内存中只会保留一个的才对额,但是 设置多个setInterval会叠加,说明setInterval方法在内存中被储存了多个吗?
问题2:console输出查看setinterval方法的原始代码得到function(){native code}点击不能查看的?浏览器好像不让我看
问题3:后来我有实验其实把setInterval()赋值给timer之后timer用console输出其实是一个数字如1,2.。。。;然后再clearinterval中输入对应的数字也是能停止定时器的,哈哈。这个数字应该是方法的返回值吧,那说明这个方法应该已经被执行完毕了,被垃圾回收机制销毁复原了吧,这样又和问题2的储存多个的情况有矛盾,想不明白了
2017-12-29 17:50  回复本帖
 
leo

问题1:你只要设置一个 setInterval,就会有一个定时器。你再设置一个 setInterval,就有两个定时器,它们不是 “叠加”,它们就是二个。


 


问题2:不太清楚你要干嘛。


 


问题3:以数字去停止有风险,万一别的浏览器不这样执行呢?浏览器的垃圾回收机制并不是完全统一的。

2017-12-29 18:20  回复本帖
 
leo

其实定时器不难理解:


 


想象一下定时器就是一个闹钟,设置一分钟后就开始叫唤。


 


你拿来一个闹钟放在桌子上,然后你给这闹钟起个名叫 timer


你又拿来一个闹钟放在桌子上,然后你想不出别的名字,你仍然管这闹钟叫 timer


 


接下来你什么都不做,静静看着它们……过了一分钟,第一个闹钟叫唤起来,然后过不了一会儿,第二个闹钟也叫唤起来了……


 


---


 


想停下它们?


你要是没有给闹钟设置不同的开关,那恭喜你了,你只能关闭一个闹钟。


 


想关上另一个?除非你关上网页,才能让闹钟停掉。

2017-12-29 18:30  回复本帖
Shark

leo 2017-12-29 18:20发表的内容:

问题1:你只要设置一个 setInterval,就会有一个定时器。你再设置一个 setInterval,就有两个定时器,它们不是 “叠加”,它们就是二个。


 


问题2:不太清楚你要干嘛。


 


问题3:以数字去停止有风险,万一别的浏览器不这样执行呢?浏览器的垃圾回收机制并不是完全统一的。

问题1我想表述的点是:window下的公共方法执行完成之后内存中只会保留一个的才对额,但是.setinterval的方法却能够在内存中保存多个的,(prototype : 写在构造函数的下面,让公用的方法或者属性在内存中存在一份 ( 提高性能 ))这两个有矛盾额?
所以我做了问题2的操作想输出setinterval看下方法内部的代码,但是得到function(){native code}点击不能查看的,想知道下有什么方法能看到window下默认的方法的内部代码?
补充:忽然感觉setInterval和监听事件.addEventListener();很像都是可以添加多个的,对addEventListener也产生了(prototype : 写在构造函数的下面,让公用的方法或者属性在内存中存在一份 ( 提高性能 ))矛盾的困惑?我觉得老师应该能get到我想要知道的点了吧,就在和面向对象结合考虑的时候,公用的方法在内存中应该只有一份的,但现在可以设置多个setinterval在内存中多次保存了,就和公共方法的一份矛盾了。

2017-12-29 18:59  回复本帖
登录 后才可以发表回复