js之闭包

一、理解

会让局部变量被永久保存, 就是这个机制不会让垃圾回收机制回收部分有用的变量

二、闭包环境

1、函数嵌套函数时,内层函数引用了外层函数作用域下的变量,并且内层函数在全局作用域下可访问,就形成了闭包

2、以上定义也是闭包经典定义,个人对于闭包的理解是,形成闭包环境后,编译器认为外层函数作用域下的变量是有用的变量,因为这个变量也确实在全局作用域下被访问了

3、那么关于闭包也可理解为,在定义变量之外的作用域访问这个变量就会形成闭包

function outerFn() {
  let a = 10;            // 不会被垃圾回收机制删除
  function innerFn() {
    a++;
    console.log(a);
  }
  return innerFn;
}

let fn = outerFn(); 
fn(); // 11
fn(); // 12
fn(); // 13

三、闭包应用

1、防抖及节流

防抖和节流都是为了减少调用频率,区别就是:

函数频繁操作,防抖只在最后一次操作时重新计时,并且只有最后一次操作才会被触发;

而节流不管事件操作多么频繁,都会在规定时间段内触发事件函数;

以下是防抖和节流的实现:

// 防抖
function debounce(fn, interval) {
  let timer = null;
  return function () {
    clearTimeout(timer);
    let args = Array.prototype.slice.call(arguments, 0);
    let _this = this;
    timer = setTimeout(() => {
      fn.apply(_this, args);
    }, interval || 300);
  };
}

let handle = debounce(() => {
  console.log("我执行了");
}, 1000);

handle();
handle();
handle();
handle();
// 节流
function throttle(fn, interval) {
  let timer = null;
  let firstTimer = true;
  return function () {
    let args = Array.prototype.slice.call(arguments, 0);
    let _this = this;
    if (firstTimer) {
      fn.apply(_this, args);
      firstTimer = null;
    }
    if (timer) return;
    timer = setTimeout(() => {
      fn.apply(_this, args);
      firstTimer = null;
    }, interval || 300);
  };
}

let req = throttle(() => {
  console.log("发送请求");
}, 1000);

req();
req();
req();
req();

2、缓存

利用了闭包能够保存部分有用的变量,以下代码利用deps缓存部分计算结果

function memorize(fn) {
  const deps = {
    "1|2": 3,
    "1|3": 4,
  };
  return function (...rest) {
    const key = rest.join("|");
    deps[key] || (deps[key] = fn(...rest));
    return deps[key];
  };
}

let execute = memorize((a, b) => {
  return a + b;
});

console.log(execute(2, 3));

你可能感兴趣的:(JavaScript,javascript,前端,html,css)