细说JS系列(十一)

52 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

铃铛说点题外话

上一篇详细的说了JS的常用和不常用的两种垃圾回收机制,这一篇我们继续说说内存管理的查漏补缺————内存泄露

铃铛说正文

我们来说说内存管理不好会出现的问题:内存泄露。

我们常说的闭包,定时器都是最容易造成内存泄露的。

那我们就借此说说闭包和定时器

闭包

我们可以理解为一个函数内在定义一个函数,内部的函数可以获取到外部函数作用域的变量,我们可以将内部的函数称为闭包。

在开始之前我们先看看几个案例

  1. 函数内部可以获取全局变量
var age = 18
function f1() {
    console.log(age)
}
f1()  //18

这里的输出结果印证了函数内部可以获取到全局变量

  1. 函数外部不能获取函数内部的变量
function f1() {
    var age = 18
}
console.log(age)  //Uncaught ReferenceError: age is not defined

这里的例子也验证了函数外部是获取不到函数内部的变量的

  1. 如果需要获取函数内部的变量的?那就是我们说的闭包可以做到了
fucntion f1(){
    var age = 18
    function f2() {
        console.log(age)   //18
    }
}

这里我们发现函数内部是可以获取到函数外部的变量的,那我们可以将内部的函数return出去,这样函数的外部就可以获取到函数内部的变量

    function f1() {
      var age = 18
      function f2() {
        console.log(age)   //18
      }
      return f2
    }
    var result = f1()
    result()

我们将内部的函数f2作为参数return出去,在函数外部使用result接收函数f1

我们也可以说在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

那大家一定还有一个疑问,闭包有什么用呢?这就跟我们常说的防抖节流

  • 防抖

在一段时间内只执行最后一次,一般用在避免按钮重复点击

function debounce(fn, delay) {
    var timer = null
    return function () {
        clearTimeout(timer)
        setTimeout(() => {
            fn.apply(this, arguments)
        }, delay)
    }
}

这里我们可以优先注意一点apply,在后文中我们会说到,这里先留个悬念

  • 节流

一段时间内只执行一次,一般用在搜索条

function throttle(fn, delay) {
    var timer = true
    if(!timer) return 
    timer = false
    setTimeout(() => {
        fn.apply(this, delay)
        tiemr = true
    }, delay)
}

这两个函数里面还有一个小点就是箭头函数,也就是定时器里面写的()=>{},这里我也会在以后的篇章中详细介绍,箭头函数和普通函数有什么区别

说回正文的内存泄露,闭包里面的函数如果在使用之后没有清除,那么这个变量就会一直存在,就会造成我上文说的内存泄漏。定时器会一段时间执行一次,那么也意味着它会一直在页面执行,也会造成内存泄露。

跟铃铛说再见

这一篇我们说了内存泄露的两种可能,并且详细的对闭包的概念、使用、开发使用都进行了详细的解释,那今天就先说到这里啦