考虑这样一个场景,我们有一个搜索框,需要在用户输入内容时列出搜索结果,我们可以用 oninput
事件来做这件事情。
oninput
和 onchange
不同之处在于 oninput
事件在 input 值发生变化是立即触发, onchange
在元素失去焦点时触发。
我们想要选用 oninput 来做这件事情,以便即时地获取到搜索的数据。
<input type="text" id="myInput" oninput="debounceSearch(this)">
可是用 oninput
会带来一个问题,比如用户想搜索 JavaScript
这个关键字,当用户输入 J
时发送一次请求数据的请求,接着输入 a
,又用 Ja
这个关键字发送一次请求,在用户输入完 JavaScript
这个关键字的过程中,我们总共发了 10 次请求,而前 9 次请求都是无效的,如果用户输入够快的话,这样就会带给服务器更大的压力,我们可以用函数防抖来解决这个问题。
函数防抖(debounce)就是当我们发送一个请求方法时,我们把请求数据的方法放到 setTimeout()
里,每次发请求之前都先 clearTimeout()
,这样用户在 setTimeout()
里规定的 delay 时间里触发 oninput
就会 clearTimeout()
,导致不发送请求,直至用户在 delay 时间里无操作,才发送请求。代码简化如下:
let timer;
function debounceSearch(e) {
let searchKeywords = e.value;
clearTimeout(timer);
timer = setTimeout(() => {
console.log(searchKeywords);
}, 250);
}
上面那种方法只是简单的演示下防抖的原理,上面那种方法扩展性较差
用闭包实现如下:
function debounce(fn, delay) {
let timer;
return function () {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
}
<input type="text" id="myInput">
调用方法类似如下:
let el = document.getElementById("myInput");
myInput.addEventListener("input", debounce(function() {
console.log(this.value)
// request method code put here
}, 250));
关于 arguments
JavaScript 的每个函数都会有一个 Arguments 对象实例 arguments,它引用着函数的实参,arguments类似于数组, 它也有类似于数组的length属性。
function func1(a, b, c) {
console.log(arguments[0]);
// expected output: 1
console.log(arguments[1]);
// expected output: 2
console.log(arguments[2]);
// expected output: 3
}
func1(1, 2, 3);
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载:
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //输出 "15"
doAdd(40, 20); //输出 "60"