day25--JS进阶(递归函数,深浅拷贝,异常处理,改变this指向,防抖及节流)

目录

浅拷贝

[1.拷贝对象①Object.assgin() ②展开运算符newObj = {...obj}拷贝对象](#1.拷贝对象①Object.assgin() ②展开运算符newObj = {...obj}拷贝对象)

[2.拷贝数组 ①Array.prototype.concat() ② newArr = ...arr](#2.拷贝数组 ①Array.prototype.concat() ② newArr = [...arr])

深拷贝

1.通过递归实现深拷贝

2.lodash/cloneDeep实现

3.通过JSON.stringify()实现

异常处理

throw抛异常

try/catch捕获异常

debugger

处理this

this指向

普通函数this指向

箭头函数this指向

改变this

call()

apply()

bind()

性能优化

防抖

[1. lodash提供的防抖函数来处理](#1. lodash提供的防抖函数来处理)

[2. 手写一个防抖函数来处理](#2. 手写一个防抖函数来处理)

节流

[1. lodash提供的节流函数来处理](#1. lodash提供的节流函数来处理)

[2. 手写一个节流函数来处理](#2. 手写一个节流函数来处理)


浅拷贝

关于对象/数组等引用数据类型直接复制出现的问题:

因为复制完后的是地址,因此修改复制后的会影响到原来的对象

需要深浅拷贝来解决。

1.拷贝对象①Object.assgin() ②展开运算符newObj = {...obj}拷贝对象

2.拷贝数组 ①Array.prototype.concat() ② newArr = ...arr

Array.prototype.concat()

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

因此用于拷贝,则先声明一个空数组再对其进行拷贝。

利用浅拷贝,遇到简单的引用数据类型可以,只是拷贝最外边一层,但是里层的仍然是拷贝地址!

因此,对于浅拷贝,对于多层会出现原本出现的问题,对于多层对象/数组,需要深拷贝。

深拷贝

1.通过递归实现深拷贝

深拷贝需要用到函数递归;如果遇到数组,利用递归处理;如果遇到对象,利用递归处理,二者顺序不可调换

javascript 复制代码
// 深拷贝函数
    function deepCopy(newObj, oldObj) {
      // 遍历旧对象
      for (let k in oldObj) {
        // 遇到值为数组的处理
        if (oldObj[k] instanceof Array) {
          // 如果值为数组,则要对该属性遍历,先要有一个空数组
          newObj[k] = []
          deepCopy(newObj[k], oldObj[k])
        } else if (oldObj[k] instanceof Object) {
          // 如果值为对象,则要对该属性遍历,先要有一个空对象
          newObj[k] = {}
          deepCopy(newObj[k], oldObj[k])
        } else {
          newObj[k] = oldObj[k]
        }

      }
    }

    deepCopy(o, obj)

2.lodash/cloneDeep实现

要先引入库

<script src="./lodash.min.js"></script>

3.通过JSON.stringify()实现

转为JSON字符串再进行拷贝

异常处理

throw抛异常

主观上在适当的地方抛出想设置的异常提示语

try/catch捕获异常

语法:try{} catch(err){} finally{}

\[\]表示可选

catch(err){} 是获取到错误信息对象,上述是将错误信息打印出来。catch(){}不会终止函数,需要手动进行return

debugger

debugger 代码中打断点,效果与在浏览器中同,只是有时更方便。

处理this

this指向

普通函数this指向

普通函数的this指向调用者

箭头函数this指向

逐层往外层函数一层层找,直至有this的定义

改变this

后两者更重要

call()

调用函数,同时改变函数中的this指向

apply()

与call()的不同点在于传递的函数形参要用数组包裹着

bind()

与前两者不同的是

其能改变this指向但!!不会调用函数

因为不调用函数,因此返回值并不是函数返回值,而是拷贝出来的原函数(新函数)

因此只是想改变this指向而不想立马调用函数时要首先想到bind()!!!

→

性能优化

一般对于触发频次比较高的时间,就需要用防抖或者节流函数来控制触发。

防抖

1. lodash提供的防抖函数来处理

(其是个函数!)

2. 手写一个防抖函数来处理
javascript 复制代码
    function debounce(fn, t) {
      let Time
      console.log(Time)
      return function () {
        if (Time) clearTimeout(Time)
        Time = setTimeout(fn, t)
      }
    }

节流

1. lodash提供的节流函数来处理

这个节流函数是指单位时间内只触发一次,如果单位时间内被触发了多次,在第一次触发结束时会被触发第二次,但不会有第三次,第四次....尽管前面触发了多次。

与手写的节流有不同,手写的节流是单位时间在最后一刻触发,且单位时间内触发了多次,仍然是最后一刻触发。

用法与上同

2. 手写一个节流函数来处理
javascript 复制代码
    function throttle(fn, t) {
      let timer
      return function () {
        // 如果没有定时器运行,则开启,开启后清空,
        // 如果有,则不开启
        console.log(timer)
        if (!timer) {
          timer = setTimeout(function () {
            fn()
            //  开启后执行完后清掉定时器(将定时器置为空),确保下一次正常执行
            // 置空一定要放在定时器内部
            timer = null
          }, t)
        }
      }
    }
相关推荐
努力努力再努力wz10 分钟前
【Lua 入门系列】Lua 函数深入理解:函数对象、多返回值、可变参数、闭包、递归与尾调用优化
开发语言·lua
jktantan19 分钟前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
飞浪纪元[FWC–FE]1 小时前
从零到一键绿:Qt 5.14.2 + VS2019 开发环境搭建、Kit 套件配置与构建错误修复完全手册
开发语言·qt
Wang's Blog1 小时前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
我命由我123451 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
架构师伯子明1 小时前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
海域云SeaArea_1 小时前
Windows Server 2008 R2 从零安装 IIS7.5(二):php.ini 配置
开发语言·windows·php
叼烟扛炮1 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
xixingzhe21 小时前
图表中同比与环比的区别:看趋势还是看变化?
开发语言·python
andyweike1 小时前
Swift
开发语言·ios·swift