以下内容,都是本人自己思考所得,不免存在很多问题,欢迎大家指正或者提供更好的解决方法。
在开发中,遇到这样一个问题:拍摄地点列表,用户如果在短时间内多次点击同一个地点时,将会添加多个同名地点。
很显然,这不是我们想要的结果。然后就上网搜了一下,知道了一个新的概念,函数节流(在这里,这个理解是错误的,应该是函数去抖,这个后面再说)。
在这里主要参照了博客园谦行的这篇文章:Javascript函数节流
这边文章主要讲述了无参数函数的节流,并提供了两种实现方式。而我在这里想要说的是这实际开发中,我遇到的含参数节流问题以及这一过程中产生的其他问题。
首先,先说明含参函数的传递方式:1.构造匿名函数 2.参数和方法分开传递 (js 把函数作为参数传递给另一个方法)
在这里,我也按照谦行的两种实现方式来分别说明:
第一种方式:
function throttle(method, context) { clearTimeout(method.tId); method.tId = setTimeout(function() { method.apply(context); }, 500); }
这里很容易看出,构造匿名函数的方法是不可取的,因为每回调用匿名函数,tid的值都是undefined,不能达到节流的目的。
onclick="throttle(function() {resizehandler('a','b');},window)"
如果直接将值与参数分开传递,需要重写throttle的方法定义,而且这样操作达不到节流函数复用的目的。我自己思考的处理方式如下(这里直接使用了arguments,目的是达到了,不知道会不会有其他影响):
<div class="container" id="div1" onclick="test('a','b')"></div> <script> function test() { throttle(resizehandler,window,arguments) } function throttle(method, context,parameters) { clearTimeout(method.tId); method.tId = setTimeout(function() { method.apply(context,parameters); }, 500); } var n = 0; function resizehandler(name, title) { console.log(++n); console.log(name); console.log(title); }
第二种实现方式:
function throttle(method, delay) { var timer = null; return function() { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function() { method.apply(context, args); }, delay); } }
因为该方法使用了函数句柄,可以通过构造匿名函数的方式来传递参数,不过也正是由于这一原因的影响,导致在事件绑定上有一定区别。
document.getElementById('div').onclick = throttle(function() { resizehandler('a','b'); }, 500);
上面代码所示的绑定方法是可行的,但直接onclick = "throttle(function() {resizehandler('a','b');}, 500)";是不可行的,返回的函数没有被调用,如果改成onclick = "throttle(function() {resizehandler('a','b');}, 500)()",函数被调用了,但是没达到节流的目的。具体原因,我也不是太懂,希望有人能够指教。
当然将函数和参数分开传递,也是能够实现的,与前一种方式没有太大区别,大家可以根据实际情况来使用。
最后,在实现的过程中,又发现了一个新的名词叫函数去抖,根据定义来说,前面我们所提到的内容应该都是函数去抖,不过细致的也没见多大区分,大家有兴趣的可以去看这篇文章:JS魔法堂:函数节流(throttle)与函数去抖(debounce)