请注意,本文转载。原地址:http://blog.csdn.net/liusaint1992/article/details/49933971
JavaScript写函数的时候,常常遇到一个函数还没有运行完就再次调用同一个函数的情况,而这种情况下就可能发生一些未预期的结果。
之前在javascript论坛上回答过一个问题,JS中图片抖动问题
它这个图片,mouseover时间会让它抖动一阵子,然后回到原来的位置,但是如果在它还没有抖动结束的时候,再去触发mouseover的时候,就会在原来的函数还没有执行完恢复到原地的时候再次执行,从而导致最终图片偏离原位。
问题代码:
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> img{width:150px; height:150px; position:absolute; top:50px; left:300px; } </style> <script> window.onload = function(){ function getStyle(obj,attr){ return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr]; } function shake(obj,attr,endFn){ var arr = []; for(var i=20;i>0;i-=2){ arr.push(i,-i); } arr.push(0); var num = 0; var origin = parseInt(getStyle(obj,attr)); obj.shake = setInterval(function(){ obj.style[attr] = origin + arr[num] + 'px'; num++; if(num == arr.length){ clearInterval(obj.shake); endFn && endFn(); } },50) } var img = document.getElementsByTagName("img")[0]; img.onmouseover = function(){ shake(this,'top'); } } </script> </head> <body> <img src="http://avatar.csdn.net/2/9/2/3_liusaint1992.jpg"> </body> </html>
方法一,用全局变量标识函数执行状态。
使用一个全局变量做标识,shaking = false。 我们执行函数之前先判断 if(shaking == false){return;}shaking = true , 然后在函数执行结束的时候加一句:shaking = false。标识函数没有在执行。
具体代码:
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> img{width:150px; height:150px; position:absolute; top:50px; left:300px; } </style> <script> window.onload = function(){ function getStyle(obj,attr){ return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr]; } var shaking = false; function shake(obj,attr,endFn){ if(shaking == true){ return; } shaking = true; var arr = []; for(var i=20;i>0;i-=2){ arr.push(i,-i); } arr.push(0); var num = 0; var origin = parseInt(getStyle(obj,attr)); obj.shake = setInterval(function(){ obj.style[attr] = origin + arr[num] + 'px'; num++; if(num == arr.length){ clearInterval(obj.shake); endFn && endFn(); shaking = false; } },50) } var img = document.getElementsByTagName("img")[0]; img.onmouseover = function(){ shake(this,'top'); } </script> </head> <body> <img src="http://avatar.csdn.net/2/9/2/3_liusaint1992.jpg"> </body> </html>
可是这样毕竟引了了一个新的全局变量,不到迫不得已的时候,我是不想引用新的全局变量的。 那么有没有不用全局变量的方法来阻止函数没执行结束的时候就再次被执行呢?最近写一个控件的时候,突然想到一种新的方法。 用起来也比较溜。
方法二:用销毁函数然后再恢复函数的方法阻止函数运行。
原理是,如果我们在执行这个函数的时候,把这个函数销毁了,函数执行结束的时候再将这个函数恢复。 在函数执行过程中,这个函数名都不存在了,自然无法调用。 一执行该函数,就给该函数做一个备份,然后销毁该函数,函数主体执行结束用备份的函数恢复我们销毁的函数。
示例代码:
运用到上面的案例中:
关键代码:
// var shaking = false; function shake(obj,attr,endFn){ // if(shaking == true){ // return; // } // shaking = true; var backup = shake;//备份 shake = null;//销毁 var arr = []; for(var i=20;i>0;i-=2){ arr.push(i,-i); } arr.push(0); var num = 0; var origin = parseInt(getStyle(obj,attr)); obj.shake = setInterval(function(){ obj.style[attr] = origin + arr[num] + 'px'; num++; if(num == arr.length){ clearInterval(obj.shake); endFn && endFn(); // shaking = false; shake = backup;//抖动结束之后恢复 } },50) }
经测试,两种方法实现了同样的效果!