【前端面试总结】谈谈闭包

104 阅读3分钟

1.谈谈你对闭包的理解

闭包可以理解为函数中的函数,其中内部函数可以访问外部函数的变量,闭包是将内部函数和外部函数连接起来的桥梁。

2. 闭包的优点

  1. 可以访问到函数内部的变量(通过函数内部的函数俩访问函数的变量);
  2. 可以避免全局变量被污染;

3.闭包的缺点

  1. 容易导致内存泄漏:因为闭包会长时间保持对外部作用域的引用,如果没有及时释放这些引用的话,会导致垃圾回收机制回收内存失败,造成内存泄漏。解决办法就是:在不需要使用闭包时,要取消对其变量的引用,例如将引用置为null。
  2. 内存消耗大:层函数每次运行都会形成一个闭包,这个闭包会保留外部作用域的变量,因此内存消耗很大。因为不能滥用闭包,否则会造成网页性能问题。

3.1 垃圾回收机制

内存泄漏:占用的内存没有被及时释放,会造成内存泄漏;
内存溢出:需要的内存超出了剩余内存,会造成内存溢出;

垃圾回收机制的回收算法:

  1. 引用计数法:“把对象是否不被需要”简化为“对象有没有其他对象引用到它”,如果该对象的引用数为0,则对其进行垃圾回收。
  2. 标记清除法:“把对象是否不被需要”简化为“对象是否可以获得”,垃圾回收器从根开始,找到所有从根开始引用的对象,然后查找这些对象引用的对象,一层一层找下去,找到所有可以获得的对象并收集所有不能获得的对象,这些不能获得的就是垃圾回收器需要回收的。

4.闭包的应用

  1. 立即执行函数

利用for循环创建几个立即执行函数,并且把变量当做参数传入,就是一个闭包。

for (var i = 0; i < list.length; i++) {
// 利用for循环创建了4个立即执行函数,每个立即执行函数都是一个闭包
(function(i) {
    list[i].onclick = function() {
      console.log(i);
    }
 })(i);
}
  1. 函数柯里化

函数式编程里面的概念,只传递一部分参数来调用它,然后返回一个函数让它处理剩下的参数。就是把一个多参数函数转化为一个单参数函数。柯里化的作用:参数复用、提前返回和延迟执行。

// 柯里化之前
function add(x, y) {
  return x + y;
}
add(1, 2) // 3

// 柯里化之后
function addX(y) {
  return function (x) {
    return x + y;
  };
}
addX(2)(1) // 3
  1. 防抖和节流

防抖:为一个事件设置一个时间N,N秒后再执行该事件,若在N秒内重复触发,则重新计时。(一定时间内多次触发一个函数,只执行最后一次)。例如:浏览器搜索框。
节流:为一个事件设置一个时间N,N秒内只执行一次,若在N秒内重复触发,则重复触发的不生效。(一定时间内多次触发一个函数,时间到了之后只执行一次函数)。例如:页面滚动。

// 防抖
function debounce(fn, wait) {
    let timer = null;
    const agrs = arguments;
    const _this = this;
    return function() {
        if (timer) {
            timer = null
        }
        timer = setTimeout(() => {
            fn && fn.apply(_this, agrs);
        }, wait);
    }
}
// 节流
function throttle(fn, wait) {
    let timer = null;
    const agrs = arguments;
    const _this = this;
    return function() {
        if (timer) {
            return;
        }
        timer = setTimeout(() => {
            fn && fn.apply(_this, agrs);
            timer = null;
        })
    }
}