闭包相关实战题

81 阅读2分钟

1、手写实现bind

// 示例对象
let foo = { name: "Bob" };
// 示例函数
function getName() {
  console.log(this.name, ...arguments);
}

// 实现过程
Function.prototype.myBind = function () {
  let that = this;
  let obj = arguments[0]; // 传入的第一个对象参数
  let otherArguments = [...arguments].slice(1); // 传入的其余参数
  return function () {
    that.call(obj, ...otherArguments, ...arguments);
  };
};

// 函数调用
let getFooName = getName.myBind(foo, "1", "2");
getFooName("3", "4"); // 输出:Bob 1 2 3 4

2、定时函数传参

function fn(a) {
  return function () {
    console.log(a);
  };
}
setTimeout(fn(123), 1000); // 1秒后输出:123

3、回调函数

function add(num1, num2, callBack) {
  let sum = num1 + num2;
  if (typeof callBack === "function") callBack(sum);
}
add(1, 2, function (sum) {
  console.log(sum);
}); // 输出:3

4、异步循环调用

for (var i = 0; i < 10; i++) {
  (function (i) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000);
  })(i);
} // 输出: 0~9每秒输出一个数字

5、小范围代替全局变量

function createCounter() {
  let count = 0; // count是私有变量,只能在createCounter函数内部进行访问
  return {
    increment: function () {
      count++; // 只能通过这个闭包来修改count的值
    },
    getCount: function () {
      return count; // 只能通过这个闭包来访问count的值
    }
  };
}

const myCounter = createCounter();
myCounter.increment();
myCounter.increment();
console.log(myCounter.getCount()); // 输出:2
console.log(myCounter.count); // 输出:undefined

6、节流防抖函数

降低性能消耗,减少资源浪费

防抖(Debouncing)

防抖的基本思想是,如果你持续处罚某件事情,函数只会在你最后一次触发事件的一段时间后执行一次。

使用场景: 比如输入框频繁输入内容、频繁点击按钮触发某个事件、监听浏览器滚动,完成某些特定操作、浏览器页面缩放resize事件

function debounce(func, wait) {
  let timer = null;
  return function () {
    const args = arguments
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}

debouncedSave = debounce(function (a) {
  console.log("函数执行!", a);
}, 500)
window.addEventListener("resize", debounceSave(123))

节流(throttle)

如果这个事件会被频繁触发,那么节流函数会按照一定频率来执行函数 不过在这个过程中触发了多少次这个事件,执行函数的频率总是固定的。

使用场景:鼠标移动事件、游戏用户点击攻击操作

function throttle(func, limit) {
  let timer = null;
  return function () {
    if (timer) { return }
    timer = setTimeout(() => {
      func.apply(this, arguments);
      timer = null;
    }, limit);

  };
}

const throttledSave = throttle(function (a) {
  console.log("函数执行!", a);
}, 1000);
window.addEventListener("scroll", () => {
  throttledSave(123)
});