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)
        }
      }
    }
相关推荐
coder!mq43 分钟前
说几个常见的语法糖?
java·开发语言·算法
gugucoding1 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ1 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大1 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS1 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
满栀5852 小时前
vue动态路由效果
前端·javascript·vue.js·前端框架·vue
quantdash_cc2 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash
ydd1001002 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
半亩码田3 小时前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
Wzx1980123 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker