作用域、闭包及其应用

闭包是有权访问另一个作用域中的变量的函数。

如果你找部门A办事,部门A说你得先去B部门盖章,部门B又说你得去部门C盖个章……这叫踢皮球。而闭包与之相反,它是负责到底,部门A的人会自动去和其他部门进行协调。

在JS中,闭包与作用域是分不开的,只要理解了作用域即可理解闭包。

一个简单闭包

在某些情况下,我们可能需要访问另一个作用域中的变量,使用函数即可创建一个作用域:

function Life(){
  let count = 0;
  return function(num){
    console.log(`Before add: ${count}`);
    count += num;
    console.log(`After add: ${count}`);
  }
}

let lifeAdd = Life();
lifeAdd(2);	//Before add: 0   After add: 2

这里return出来的函数其实就是闭包给外界的一个接口,如果不这样,给外层作用域中的对象设置一个方法也可以,比如window:

function Life(){
  let count = 0;
  window.lifeAdd = function(num){
    console.log(`Before add: ${count}`);
    count += num;
    console.log(`After add: ${count}`);
  }
}
Life();
lifeAdd(2);	//Before add: 0   After add: 2

虽然Life函数已经执行完毕,但由于闭包的存在,Life函数的内部变量一直没有被销毁。

闭包:函数防抖(debounce)与函数节流(throttle)

在实际应用中,控制一段代码的执行时机是很常见的。

有两个很常见的场景类型:

防抖(debounce)

在高频率触发的事件中,两次触发的时间间隔超过一定限度时才执行处理函数,否则重新计时。

就像电梯一样,每进去一个人,电梯就重新计时,几秒钟之后再无人进入时才会关门。

function debounce(fn, interval = 300) {
    let timeout = null;
    return function () {
        clearTimeout(timeout);
        timeout = setTimeout(fn, interval);
    };
}
//每次触发事件时,都会设置新的定时器,清除已有定时器
//而如果事件触发间隔超过了300毫秒,已有的定时器就会执行它的回调函数
window.onmousemove = debounce(function(){console.log('---')}, 300)

上面的debounce函数没有向回调函数传递参数,下面是带参数版:

function debounce(fn, interval = 300) {
    let timeout = null;
    return function () {
        clearTimeout(timeout);
        timeout = setTimeout(
          ()=fn((new Date()).toLocaleString()),	
          interval
        );
    };
}
//假设回调函数每次执行都需要打印一个字符串
window.onmousemove = debounce(function (str){
    console.log(str)
}, 300)

节流

在高频率触发的事件中,不论触发频率变得多高,都是每隔一段时间执行一次处理函数。

const throttle = (func, wait) = {
  let timer = null;
  return () = {
    if (timer) {
      return;
    }

    timer = setTimeout(() = {
      func((new Date()).toLocaleString());
      timer = null;
    }, wait);
  };
};
window.onmousemove = throttle(function (time){
    console.log(time)
}, 1000)

防抖与节流的最大区别就是,防抖是只有在事件触发慢下来的时候才执行,而节流是以恒定的频率执行。

posted @ 2020-05-16 14:03  Paykan  阅读(183)  评论(0编辑  收藏  举报