以下内容,都是本人自己思考所得,不免存在很多问题,欢迎大家指正或者提供更好的解决方法。
在开发中,遇到这样一个问题:拍摄地点列表,用户如果在短时间内多次点击同一个地点时,将会添加多个同名地点。
很显然,这不是我们想要的结果。然后就上网搜了一下,知道了一个新的概念,函数节流(在这里,这个理解是错误的,应该是函数去抖,这个后面再说)。
在这里主要参照了博客园谦行的这篇文章: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)