guqzhou guqzhou
首页
快捷导航
下载站
  • Html 篇
  • Javascript 基础篇
  • 框架

    • Vue2
  • 前端文章

    • Css 篇
    • 微信开发
    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 面试题库

    • HTML
    • CSS
    • jQuery
    • Vue
    • 零碎
  • 面试心得

    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
关于
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue资源
  • 主站CDN
  • Vercel
  • Netlify
  • Github
GitHub

guqzhou

喜欢所以去追求!
首页
快捷导航
下载站
  • Html 篇
  • Javascript 基础篇
  • 框架

    • Vue2
  • 前端文章

    • Css 篇
    • 微信开发
    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 面试题库

    • HTML
    • CSS
    • jQuery
    • Vue
    • 零碎
  • 面试心得

    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
关于
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue资源
  • 主站CDN
  • Vercel
  • Netlify
  • Github
GitHub
  • vue2
  • CSS

  • Javascript基础

    • js介绍
    • 数据类型
    • js检查数据类型的方法
    • 内存泄漏
    • 说一下闭包,并且有什么特点
    • 页面加载和滚动事件
    • 闭包
      • 回顾知识
      • 闭包
        • 闭包概念
        • 在谷歌浏览器调试闭包
      • 闭包的作用
      • 内存泄漏和内存溢出
        • 内存泄漏
        • 内存溢出
      • 闭包的应用场景
        • 高阶函数
        • 函数的坷里化
        • 防抖和节流
    • DOM
    • 重绘和回流
    • 原型、原型链和继承
  • javascript进阶

  • typeScipt

  • vue2

  • vue3

  • react

  • vue实战

  • pinia的使用

  • gis

  • 前端文章

  • JavaScript文章

  • Vue文章

  • 小程序开发文章

  • uni-app

  • 学习笔记

  • TaroUI的使用

  • 工具使用

  • 前端
  • Javascript基础
guqzhou
2022-01-26
0

闭包

  • 回顾知识
  • 闭包
    • 闭包概念
    • 在谷歌浏览器调试闭包
  • 闭包的作用
  • 内存泄漏和内存溢出
    • 内存泄漏
      • 常见的内存泄漏
    • 内存溢出
      • 闭包是否会产生内存泄漏
  • 闭包的应用场景
    • 高阶函数
      • 接收函数作为参数
      • 函数作为返回值
    • 函数的坷里化
      • 应用场景:迭代商品送福利的计算
    • 防抖和节流
      • 防抖
        • Demo演示
      • 节流
        • Demo演示
      • 总结

# 回顾知识

根据作用域的不同,分为全局变量和局部变量,函数外部的叫全局变量,函数内部叫局部变量,分为以下三点

  • 函数内部是可以使用函数外部的全局变量的
  • 函数外部是不能使用函数内部的局部变量的
  • 当函数执行完以后,函数内部局部变量就会销毁

话不多说上代码:

    function fun() {
        var a = 10
    }
    console.log(a) // 报错为a为定义:Uncaught ReferenceError: a is not defined
1
2
3
4

但这时候我们又想让a变量在函数外部能够被访问,我们又该咋办?就引入了闭包这个概念

# 闭包

# 闭包概念

javascipt高级设计:指有权访问另一个函数作用域中的变量函数
个人定义:函数外部有权访问函数内部的变量,意味着函数内部就为局部变量

例如:上代码:

    function fun() {
        let a = 1
        return function() {
            console.log(a)
        }
    }
    // fun()  调用之后得到一个函数
    // 相当于 function() {console.log(a)} 匿名函数
    let rersult = fun() // 把匿名函数赋值给result
    rersult() // 调用函数
1
2
3
4
5
6
7
8
9
10

打印结果:

   1
1

说明:

fun为闭包函数,return函数只起到让闭包函数外部能够访问闭包函数内部的变量作用

# 在谷歌浏览器调试闭包

image-20230126073655816

说明:scope为作用域,local为局部,closure为闭包,a为闭包函数的局部变量,gloabal全局作用

# 闭包的作用

  • 延伸了变量的作用范围(延长局部变量的生命周期)
  • 函数外部可以操作函数内部的数据

上代码:

    function fun1() {
        let b = 5 
        return function () {
            b ++
            console.log(b)
        }
    }
    const result = fun1()
    result() // 6
    result() // 7
1
2
3
4
5
6
7
8
9
10

分析:

  1. fun1函数执行完成以后,由于return了一个函数变量b不会立马销毁,只有在闭包函数外部使用完以后才会销毁
  2. 闭包函数外部是看不到b变量的,但是可以在外部操作它

# 内存泄漏和内存溢出

# 内存泄漏

内存泄漏:占用的内存没有及时清理
影响:内存泄漏次数积累多了,就会导致内存溢出

# 常见的内存泄漏

  • 意外的全局变量
  • 没有及时清理定时器或者回掉函数
  • 闭包

例如内存泄漏1:

   
   function fun() {
       let a = new Array(1)
       console.log(a)
   }
   fun() // a为全局变量[]数组
1
2
3
4
5
6

例如内存泄漏2:

   let timer = ''
   timer = setInterval(() => {
       console.log('清理计时器')
   },1000)

   // clearInterval(timer) 清除计时器
1
2
3
4
5
6

例如内存泄漏3:

   function fun1() {
       let b = 5
       return function () {
           b ++
           console.log(b)
       }
   }
   let result = fun1()
   // result = null 回收闭包

1
2
3
4
5
6
7
8
9
10

# 内存溢出

程序运行时候出现错误。程序运行所需内存超过剩余内存,就会出现内存溢出的错误

例如:

    let obj = {}
    for (let i = 1 ; i < 1000; i++) {
        obj[i] = new Array(20)
        console.log('@@@')
        //把所有的数组都放到obj里面保存,导致obj占用很大的内存
    }
1
2
3
4
5
6

# 闭包是否会产生内存泄漏

一般情况下是不会的,这种情况是预期的,除非代码质量不高,滥用代码。因为内存泄漏是非预期的,本来想回收掉但没回收

# 闭包的应用场景

# 高阶函数

常见的高阶函数:Promise、setTimeout、arr.map()

# 接收函数作为参数

上代码:

    function fun(callback) {
        callback && callback()
    }
    fun(function () { console.log (666)})
1
2
3
4

# 函数作为返回值

上代码:

    function fun(fn) {
        return function() {
            console.log('函数作为返回值')
        }
    }
    fun()
1
2
3
4
5
6

# 函数的坷里化

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式 上代码:

    function fun(a,b,c) {
        return b => {
            return c => {
                return a+b+c
            }
        }
    }
    let resolut = fun(1)(2)(3)
    console.log(resolut) // 6
1
2
3
4
5
6
7
8
9

# 应用场景:迭代商品送福利的计算

# 防抖和节流

# 防抖

官方:触发高频事件后一段时间(wait)只会执行一次函数,如果指定时间(wait)内高频事件再次被触发,则重新计算时间。
个人理解:重复执行的函数,在规定时间内,只执行最后一次。频率:一次

上代码封装:

    function debounce(fn,delay) {
        let t = null 
        return function() {
            if (t) clearTimeout(t)
            t = setTimeout(() => {
                fn.apply(this)
            },delay)
        }
    }
1
2
3
4
5
6
7
8
9

应用场景:

input输入框的模糊查询、提交按钮、

# Demo演示

可用F12开发者工具查看元素及样式,可打开codepen在线编辑代码。

<html>
  <input type="text" id = "demo-debounce-input" />
</html>
<script>
    function debounce(fn,delay) {
        let t = null
        return function() {
            if (t) clearTimeout(t)
            t = setTimeout(() => {
                fn.apply(this)
            },delay)
        }
    }
    function fnc() {
        console.log('接口请求')
    }
    // 1.input输入框的模糊查询
    // let demoDebounceInput = document.getElementById('demo-debounce-input')
    // demoDebounceInput.oninput = debounce(fnc,500)
</script>
<style>
    
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 节流

官方:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效
个人理解:一个函数执行一次后,大于设定周期才会执行第二次。频率:多次。

上代码封装:

    function throttle(fn,delay = 200) {
        let flag = true
        return function () {
            if(!flag) {
                return
            }
            flag = false
            setTimeout(() => {
                fn.apply(fn)
                flag = true
            },delay)
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13

应用场景:

window对象的resize、scroll事件、鼠标的移动事件,比较适合动画相关的场景

# Demo演示

可用F12开发者工具查看元素及样式,可打开codepen在线编辑代码。

<html>
    <div class="demo-throttle">演示节流</div>
</html>
<script>
    function throttle(fn,delay = 200) {
        let flag = true
        return function () {
            if(!flag) {
               return
            }
            flag = false
            setTimeout(() => {
                fn.apply(fn)
                flag = true
            },delay)
        }
    }
    function fnc() {
        console.log('接口请求')
    }
    // 1.window的scoll
    // window.addEventListener('scroll', throttle(fnc,5000))
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 总结

防抖和节流貌似很相似,但是节流你可以想象一下水坝,你在河道中建了水坝,不能让水不流动,只能让它流慢点;换言之,不能让用户的方法都不执行,如果这样干就是防抖。

再简单的说:防抖指的是只要你动作不停,就不会执行;而节流指的是规定时间内必须执行一次;一个上限,一个为下限。

上次更新: 2023/01/29, 11:01:00
页面加载和滚动事件
DOM

← 页面加载和滚动事件 DOM →

最近更新
01
面向对象
01-05
02
typescript用localStorage封装过期时间
01-05
03
npm、pnpm、yarn删除文件缓存
12-14
更多文章>
Theme by Vdoing | Copyright © 2021-2024 guqzhou | 萌ICP备20238188号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式