JavaScript-异常与this处理与性能优化

1. 深浅拷贝

在这里插入图片描述

    const obj = {
      uname: 'nidie',
      age: 18
    }
    // o对象直接复制obj,直接赋值将obj的地址也给了o
    const o = obj
    // 正常打印18
    console.log(o);
    // 对o改动,打印obj,obj也被改动了
    o.age = 20
    console.log(o);
    console.log(obj);

1.1 浅拷贝

在这里插入图片描述
拷贝对象:Object.assgin()
拷贝数组:Array.prototype.concat()

    const obj = {
      uname: 'nidie',
      age: 18
    }

    // 浅拷贝
    const o = { ...obj }
    console.log(o);
    // 对未改动的obj没有影响
    o.age = 20
    console.log(o)
    console.log(obj);

    console.log('----------------------');

    // 利用assign方法浅拷贝
    const oo = {}
    Object.assign(oo, obj)
    oo.age = 20
    console.log(oo);
    console.log(obj);

    console.log('----------------------');

    // 但是浅拷贝仍然存在问题
    const objj = {
      uname: 'nidie',
      age: 18,
      family: {
        baby: 'son'
      }
    }
    const ooo = {}
    Object.assign(ooo, objj)
    // 简单数据类型age直接赋值没关系,obj对象中存储的family地址会给ooo
    ooo.age = 20
    ooo.family.baby = '牛魔'
    // 只想改变ooo的family对象里面的属性,却把objj的也改了
    console.log(ooo);
    console.log(objj);

总结:

在这里插入图片描述

1.2 深拷贝

在这里插入图片描述

递归实现深拷贝

在这里插入图片描述

    function getTime() {
      document.querySelector('div').innerHTML = new Date().toLocaleString()
      // 每隔一秒调用一次自己
      setTimeout(getTime, 1000)
    }
    getTime()

注意:

  1. 利用函数递归
  2. 普通属性直接赋值,遇到复杂数据类型,数组,对象则调用自己
  3. 数组的逻辑顺序要在对象前面
    const obj = {
      uname: 'nidie',
      age: 18,
      hobby: ['lu', 'lulu'],
      family: {
        baby: 'babybaby'
      }
    }
    const o = {}

    // 将obj拷贝给o
    function deepCopy(newObj, oldObj) {
      // 遍历旧对象
      for (let k in oldObj) {
        // if的逻辑顺序不能反,因为数组也属于对象,必须先筛选完数组再写对象
        // 处理数组的问题
        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 {
          // k  属性名  oldObj[k] 属性值
          // newObj[k] === o.uname
          newObj[k] = oldObj[k]
        }
      }
    }
    deepCopy(o, obj) //o新对象 obj旧对象

    o.age = 20
    o.hobby[0] = 'bulu'
    o.family.baby = '牛魔'
    console.log(o);
    console.log(obj);

利用库函数直接深拷贝

  <script src="lodash.js"></script>
  <script>
    const obj = {
      uname: 'nidie',
      age: 18,
      hobby: ['lu', 'lulu'],
      family: {
        baby: 'babybaby'
      }
    }
    const o = _.cloneDeep(obj)
    console.log(o);

利用JSON实现深拷贝

    const obj = {
      uname: 'nidie',
      age: 18,
      hobby: ['lu', 'lulu'],
      family: {
        baby: 'babybaby'
      }
    }
    // 把对象转换为JSON字符串
    console.log(JSON.stringify(obj));

    // parse方法再将字符串转换为对象
    const o = JSON.parse(JSON.stringify(obj))
    console.log(o);
    
    o.family.baby = '牛魔'
    console.log(o)
    console.log(obj);;

总结

在这里插入图片描述

2. 异常处理

2.1 throw抛异常

在这里插入图片描述

    function fn(x, y) {
      if (!x || !y) {
        // throw '你没传参'
        // 抛出异常并终止程序
        throw new Error('没传参')
      }

      return x + y
    }
    console.log(fn());

总结

在这里插入图片描述

2.2 try/catch捕获异常

在这里插入图片描述

<body>
  <p>123</p>
  <script>
    function fn() {
      try {
        const p = document.querySelector('.p')
        p.style.color = 'red'
      }
      catch (err) {
        console.log(err.message);

        // 配合throw使用
        throw new Error('错了吧人才')
        return
      }
      finally {
        // 不管程序是否正确,一定会执行finnaly
        alert('你好')
      }
      // catch会拦截错误,但是不会中断程序执行  加入return中断程序
    }
    fn()
  </script>
</body>

总结

在这里插入图片描述

2.3 debugger

在这里插入图片描述

3. 处理this

3.1 this指向-普通函数

对于普通函数来说,谁调用,this就指向谁
在这里插入图片描述

总结

在这里插入图片描述

3.2 this指向-箭头函数

箭头函数this一层层往上找,找到最近的对象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 改变this

call

在这里插入图片描述

apply

在这里插入图片描述

    const obj = {
      age: 18
    }
    function fn(x, y) {
      console.log(this);
      console.log(x + y);
      return x + y
    }
    // 调用函数,并且让fn中的this指向了第一个参数obj
    // apply第二个参数必须放数组
    fn.apply(obj, [1, 2])

    // 本身就是在调用函数,所以返回值就是函数的返回值
    console.log(fn.apply(obj, [1, 2]));

bind

call()apply()不同的是,bind不会立即调用函数

在这里插入图片描述

    const obj = {
      age: 18
    }
    function fn() {
      console.log(this);
    }
    // bind不会调用函数
    // 可以改变this指向
    // 返回值是一个更改过this的函数
    const fun = fn.bind(obj)
    fun()

    // 需求:有一个按钮,点击里面就禁用,2秒钟后开启
    const btn = document.querySelector('button')
    btn.addEventListener('click', function () {
      // 禁用按钮
      this.disabled = true###
      setTimeout(function () {
        // 在普通函数中的话,要将this指向的window改为btn
        this.disabled = false
      }.bind(this), 2000);
    })

总结

在这里插入图片描述

4. 性能优化

4.1 防抖(debounce)

在这里插入图片描述

  <script src="lodash.js"></script>
  <script>
    // 鼠标在盒子中滑动,数字显示+1
    const box = document.querySelector('.box')
    let i = 1
    function mouseMove() {
      // 存在大量消耗性能的代码,dom操作、数据处理,可能造成卡顿
      box.innerHTML = i++
    }

    // box.addEventListener('mousemove', mouseMove)

    // 利用库函数lodash防抖函数
    // _.debounce(fun,时间)
    box.addEventListener('mousemove', _.debounce(mouseMove, 500))
  </script>

    // 手写防抖函数
    // 利用setTimeout定时器实现
    // 1. 声明定时器变量
    // 2. 每次鼠标移动的时候都要先判断是否有定时器,如果有的话先清除以前的
    // 3. 如果没有定时器,就开启定时器,存入到定时器变量中
    // 4. 定时器里面写函数调用
    function debounce(fn, t) {
      let timer
      // return 返回一个匿名函数
      return function () {
        if (timer) clearInterval(timer)
        timer = setTimeout(function () {
          fn()
        }, t)
      }
    }
    box.addEventListener('mousemove', debounce(mouseMove, 100))

4.2 节流

在这里插入图片描述

在这里插入图片描述

    // 利用节流实现性能优化
    // 鼠标在盒子中滑动,数字显示+1
    const box = document.querySelector('.box')
    let i = 1
    function mouseMove() {
      // 存在大量消耗性能的代码,dom操作、数据处理,可能造成卡顿
      box.innerHTML = i++
    }
    // 利用lodash库实现节流,500ms之后采取一次+1
    // 语法:_.throttle('mousemove'),_.throttle(mouseMove,500)
    box.addEventListener('mousemove', _.throttle(mouseMove, 3000))

总结

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/239898.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI日报:苹果为使用Mac的人工智能开发者推出开源工具

文章目录 总览主要介绍开发理念开发细节MLX功能用途 MLX可以用于商业软件吗&#xff1f; 总览 苹果正在为开发人员提供新的工具&#xff0c;用于在其硬件上训练和运行大型语言模型。 主要介绍 开发理念 苹果公司通过发布一系列新的开源人工智能工具&#xff0c;向开源人工智能…

java jvm堆内存分析工具MAT(导出运行中jvm堆内存、加载导出文件分析)

下载地址&#xff1a;https://eclipse.dev/mat/downloads.php 历史版本&#xff1a;https://eclipse.dev/mat/previousReleases.php jdk1.8这些老版本jdk需要使用历史版本的&#xff0c;我的是1.8&#xff0c;用的1.10的mat 我下载的地址&#xff1a;https://www.eclipse.org/d…

C# 使用异步委托获取线程返回值

写在前面 异步委托主要用于解决 ThreadPool.QueueUserWorkItem 没有提供获取线程执行完成后的返回值问题。异步委托只能在.Net Framework 框架下使用&#xff0c;.Net Core中会报平台错误&#xff0c;而且使用Task.Result来获取返回值&#xff0c;可以达成同样的目的&#xff…

区块链技术的未来,了解去中心化应用的新视角

小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 随着…

Python与ArcGIS系列(十五)根据距离抓取字段

目录 0 简述1 实例需求2 arcpy开发脚本0 简述 在处理gis数据的时候,会遇到这种需求:将一个图层与另一个图层中相近的要素进行字段赋值。本篇将介绍如何利用arcpy及arcgis的工具箱实现这个功能。 1 实例需求 为了介绍这个功能的实现,我们需要有一个特定的功能需求。在这里选…

Mac如何设置control+space切换上一中输入法

#设置方法# *搜索输入法 系统设置-搜索&#xff1a;输入法&#xff0c;并点击键盘快捷键 *点击输入法&#xff0c;勾选&#xff1a;选择上一个输入法&#xff0c;点击完成。

ServletJSP

Servlet 1.Servlet生命周期 2.HttpServletRequest与HttpServletResponse 2.1HttpServletRequest 获取请求参数 请求乱码问题&#xff1a; 请求转发 request作用域 2.2HttpServletResponse 输出 乱码 重定向 3.Cookie 4.Sessions 5.ServletContext 获取方式及常用方法&a…

【Spring教程17】Spring框架实战:实例详解解读AOP通知类型的使用

欢迎大家回到《Java教程之Spring30天快速入门》&#xff0c;本教程所有示例均基于Maven实现&#xff0c;如果您对Maven还很陌生&#xff0c;请移步本人的博文《如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》&#xff0c;本文的上一篇为《AOP配置管理中AOP切入点表…

ubuntu如何远程ssh登录Windows环境并执行测试命令

ubuntu如何远程ssh登录Windows环境并执行测试命令 1 paramiko模块简介1.1 安装paramiko1.2 paramiko基本用法1.2.1 创建SSHClient实例1.2.2 设置主机密钥策略1.2.3 连接SSH服务器1.2.4 执行命令1.2.5 关闭SSH连接1.2.6 异常处理 2 windows的配置2.1 启动OpenSSH服务2.2 配置防火…

JMeter直连数据库

JMeter直连数据库 使用场景操作步骤 使用场景 用作请求的参数化 登录时需要的用户名&#xff0c;密码可以从数据库中查询获取 用作结果的断言 添加购物车下订单&#xff0c;检查接口返回的订单号&#xff0c;是否与数据库中生成的订单号一致 清理垃圾数据 添加商品后&#xff…

Gin之GORM 操作数据库(MySQL)

GORM 简单介绍 GORM 是 Golang 的一个 orm 框架。简单说&#xff0c;ORM 就是通过实例对象的语法&#xff0c;完成关系型数据库的操作的技术&#xff0c;是"对象-关系映射"&#xff08;Object/Relational Mapping&#xff09; 的缩写。使用 ORM框架可以让我们更方便…

Kotlin+Apache HttpClient+代理服务器=高效的eBay图片爬虫

引入 你是否想过用Kotlin来编写爬虫程序&#xff1f;你是否想过用Apache HttpClient来处理HTTP请求和响应&#xff1f;你是否想过用代理服务器来绕过反爬措施&#xff1f;如果你的答案是肯定的&#xff0c;那么本文将为你介绍一种高效的eBay图片爬虫的实现方式&#xff0c;让你…

深入理解 Kafka 集群管理与最佳实践

构建和管理一个稳定、高性能的Kafka集群对于实现可靠的消息传递至关重要。本文将深入研究Kafka集群的各个方面&#xff0c;包括集群搭建、节点配置、分区与副本管理、安全性与监控&#xff0c;为读者提供全面的指导和实例代码。 1. 搭建 Kafka 集群 1.1 Broker 节点 在Kafka…

C++11 【初识】

C11简介 1.在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。 2.不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合…

java版Spring Cloud+Spring Boot+Mybatis之隐私计算 FATE - 多分类神经网络算法测试

一、说明 本文分享基于 Fate 使用 横向联邦 神经网络算法 对 多分类 的数据进行 模型训练&#xff0c;并使用该模型对数据进行 多分类预测。 二分类算法&#xff1a;是指待预测的 label 标签的取值只有两种&#xff1b;直白来讲就是每个实例的可能类别只有两种 (0 或者 1)&…

【运维】Kafka高可用: KRaft(不依赖zookeeper)集群搭建

文章目录 一. kafka kraft 集群介绍1. KRaft架构2. Controller 服务器3. Process Roles4. Quorum Voters 二. 集群安装1. 安装1.1. 配置1.2. 格式化 2. 启动测试2.1. 启功节点服务2.2. 测试 本文主要介绍了 kafka raft集群架构&#xff1a; 与旧架构的不同点&#xff0c;有哪些…

ISP去噪(2)_np 噪声模型

#灵感# ISP 中的去噪&#xff0c;都需要依赖一个噪声模型。很多平台上使用采集的raw进行calibration&#xff0c;可以输出这个模型&#xff0c;通常称为 noise profile。 名词解释&#xff1a; Noise profile 似乎可以翻译成“噪声档案”&#xff0c;其含义是某个噪声源&…

昇腾910安装驱动出错,降低Centos7.6的内核版本

零、问题描述&#xff1a; 在安装Atlas800-9000服务器的驱动的时候&#xff0c;可能会出现错误&#xff1a;Dkms install failed, details in : /var/log/ascend_seclog/ascend_install.log 如下所示&#xff1a; [rootlocalhost ~]# ./Ascend-hdk-910-npu-driver_23.0.rc3_l…

数字孪生项目的开发框架

数字孪生的开发框架提供了一套工具和API&#xff0c;使开发者能够创建和管理数字孪生模型。这些框架通常包括虚拟建模、仿真、数据集成和分析等功能。以下是一些常见的数字孪生开发框架&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发…

python matplotlib set_aspect

说明: # 设置轴比例相等&#xff0c;以获得圆柱体视角 ax.set_aspect(equal) 代码案例: import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np# 创建数据 theta np.linspace(0, 2*np.pi, 100) z np.linspace(0, 1, 100) r z**2 …