当前位置: 首页 > news >正文

JavaScript进阶-高阶技巧

文章目录

  • 高阶技巧
    • 深浅拷贝
      • 浅拷贝
      • 深拷贝
    • 异常处理
      • throw抛异常
      • try/caych捕获异常
      • debugger
    • 处理this
      • this指向
      • 改变this
    • 性能优化
      • 防抖
      • 节流


高阶技巧

深浅拷贝

只针对引用类型

浅拷贝

拷贝对象后,里面的属性值是简单数据类型直接拷贝值,如果属性值是引用数据类型则拷贝的是地址
常见语法:
1.拷贝对象:Object.assgin(新变量,被拷贝对象)const 变量名 = {...对象}
2.拷贝数组:Array.prototype.concat()[...arr]
注意:如果是简单数据类型拷贝值,引用数据类型拷贝的是地址(如果是单层对象没有问题,如果是多层对象就有问题)

深拷贝

拷贝的是对象,不是地址
常见方法:

  • 通过递归实现深拷贝
    函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
    由于递归容易发生“栈溢出”错误。所以必须要加退出条件return
const obj = {uname:'pink',age:18,hobby:['乒乓球','足球'],family:{baby:'xiaop'}
}
const o = {}
// 拷贝函数
// 深拷贝,拷贝的新对象不会影响旧对象,遇到数组和对象就再次调用递归函数,先数组再对象
function deepCopy(newObj,oldObj) {for(let k in oldObj) {// 一定先写数组,在写对象,因为万物皆对象// 处理数组的问题if (oldObj[k] instanceof Array) {newObj[k] = []// 函数递归deeepCopy(newObj[k],oldObj[k])} // 处理对象的问题else if (oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k],oldObj[k])} else {// k属性名,oldObj[k]属性值// newObj[k] === o.unamenewObj[k] = oldObj[k]}}
}
deepCopy(o,obj)// 函数调用两个参数
o.age = 20
console.log(o)
o.hobby[0] = '篮球'
o.family.baby = 'oldp'
console.log(obj)
  • lodash/cloneDeep
    JavaScript库lodash里面cloneDeep内部实现了深拷贝
    语法:const deep = _.cloneDeep(object)
<!-- 先引用 -->
<script src="./lodash.min.js"></script>
<script>const obj = {uname:'pink',age:18,hobby:['乒乓球','足球'],family:{baby:'xiaop'}}const o = _.cloneDeep(obj)o.family.baby = 'oldp'console.log(obj)
</script>
  • 通过JSON.stringfy()实现
const obj = {uname:'pink',age:18,hobby:['乒乓球','足球'],family:{baby:'xiaop'}
}
// JSON.stringify() 把对象转换为JSON字符串
// JSON.parse() 把JSON字符串转换为对象
const o = JSON.parse(JSON.stringify(obj))
o.family.baby = 'oldp'
console.log(obj)

异常处理

异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

throw抛异常

1.throw抛出异常信息,程序也会终止执行
2.throw后面跟的是错误提示信息
3.Error对象配合throw使用,能够设置更详细的错误信息

function fn(x,y) {if (!x || !y) {// throw '没有参数传递进来'throw new Error('没有参数传递进来')}return x + y
}

try/caych捕获异常

通过try/catch捕获错误信息(浏览器提供的错误信息)
1.try…catch用于捕获错误信息
2.将预估可能发生了错误的代码写在try代码段中
3.如果try代码段中出现错误后,会执行catch代码段,并截获到错误信息
4.finally不管是否错误,都会执行

function fn() {try {// 可能发生错误的代码要写到tryconst p = document.querySelector('.p')p.style.color = 'red'  } catch (err) {// 拦截错误,提示浏览器提供的错误信息,但是不中断程序的执行console.log(err.message)// 需要return中断程序,可以用throw代替throw new Error('错误')} finally {// 不管你程序对不对,一定会执行的代码alert('弹出对话框')}
}

debugger

在代码中需要调试的地方写debugger,打开控制台后自动来到debugger的位置,类似于断点
在这里插入图片描述

处理this

this指向

  • 普通函数
    普通函数的调用方式决定了this的值,即谁调用就指向谁
    普通函数没有明确调用者时this值为window,严格模式下没有调用者时this的值为undefined
  • 箭头函数
    箭头函数中的this与普通函数完全不同,也不受调用方式影响,事实上箭头函数中并不存在this
    1.箭头函数会默认帮我们绑定外层this的值,所以在箭头函数中this的值和外层的this是一样的
    2.箭头函数中的this引用的就是最近作用域中的this
    3.向外层作用域中,一层一层查找this,直到有this的定义
    注意:
    1.在开发中使用箭头函数前需要考虑函数中this的值,事件回调函数使用箭头函数时,this为全局变量时,this为全局的window
    因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数
    2.同样由于箭头函数this的原因,基于原型的面向对象也不推荐采用箭头函数

改变this

  • call()
    使用call()方法调用函数,同时指定被调用函数中的this的值
    语法:fn.call(thisArg,arg1,arg2,...)
    thisArg:在fn函数运行时指定的this值
    arg1,arg2:传递的其他参数
    返回值就是函数的返回值,因为它就是调用函数
  • apply()
    使用apply()方法调用函数,同时指定被调用函数中的this的值
    语法:fn.apply(thisArg,[argsArray])
    thisArg:在fn函数运行时指定的this值
    argsArray:传递的值,必须包含在数组里面
    返回值就是函数的返回值,因为它就是调用函数
    因此apply()主要跟数组有关系,比如使用Math.max()求数组的最大值
const obj = {age:18
}
function fn(x,y) {console.log(this)// {age:18}console.log(x + y)// 3
}
// 调用函数
// 改变this指向
fn.apply(obj,[1,2])
// 3.返回值 就是函数的返回值// 使用场景:求数组最大值
const arr = [1,2,3]
const max = Math.max.apply(Math,arr)
// console.log(Math.max(...arr))
console.log(max)// 3
  • bind()(重点)
    bind()方法不会调用函数,但是能改变函数内部this指向
    语法:fn.bind(thisArg,arg1,arg2...)
    thisArg:在fn函数运行时指定的this的值
    arg1,arg2:传递的其他参数
    返回由指定的this值和初始化参数改造的原拷贝函数(新函数)
    因此当我们只是想改变this指向,并且不想调用这个函数的时候,可以使用bind,比如改变计时器内部的this指向
const obj = {age:18
}
function fn() {console,log(this)
}
// 返回值是个函数,但是这个函数里面的this是更改过的
const fn = fn.bind(obj)
// console.log(fn)
fn()// {age:18}
<body><button>发送</button><script>// 需求,有一个按钮,点击里面就禁用,2秒钟之后开始const btn = document.querySelector('button')btn.addEventListener('click', function() {// 禁用按钮this.display = true//this指向btnsetTimeout(function() {// 在这个普通函数里面,要this由原来的window改为btnthis.disabled = false}.bind(this),2000)//这个this是上面指向btn的this})</script>
</body>

性能优化

防抖

防抖:单位时间内,频繁触发事件,只执行最后一次
使用场景:
1.搜索框搜索输入。只需要用户最后一次输入完,再发送请求
2.手机号、邮箱验证输入检测
在这里插入图片描述
常用方法:

  • lodash提供的防抖来处理
    语法:_.debounce(func,[wait=0],[options=])
    func:要防抖的函数
    [wait=0]:需要延迟的毫秒数
    [options=]:选项对象
  • 手写防抖函数
    核心思路:利用定时器(setTimeout)来实现

例如:

<style>.box {width:500px;height:500px;background-color:#ccc;color:#fff;text-align:center;font-size:100px;}
</style>
<body><div class="box"></div><script src='./lodash.min.js'><script>// 利用防抖实现性能优化// 需求:鼠标在盒子上移动,里面的数字就会变化+1const box = document.querySelector('.box')let i = 1function mouseMove() {box.innerHTML = i++// 如果里面存在大量消耗性能的代码,比如DOM操作、数据处理,可能造成卡顿}// 添加事件// box.addEventListener('mousemove',mouseMove)// 利用lodash库实现防抖 500毫秒之后+1box.addEventListener('mousemove',_.debounce(mouseMove,500))// 手写函数部分// 1.声明定时器变量// 2.每次鼠标移动(事件触发)的时候都要先判断是否有定时器,如果有先清除以前的定时器// 3.如果没有定时器,则开启定时器,存入到定时器变量里面// 4.定时器里面写函数调用function debounce(fn,t) {let timer// return返回一个匿名函数return function() {if(timer) {clearTimeout(timer)}	timer = setTimeout(function() {fn()//加小括号调用fn函数},t)	}}box.addEventListener('mousemove',debounce(mouseMove,500))</script>
</body>

节流

节流:单位时间内,频繁触发事件,只执行一次
使用场景:
高频事件:鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll
在这里插入图片描述
常用方法:

  • lodash提供的节流函数来处理
    语法:_.throttle(func,[wait=0],[options=])
    func:要节流的函数
    [wait=0]:需要节流的毫秒数
    [options=]:选项对象
    [options.leading=true]:指定调用在节流开始前
    [options.leading=false]:指定调用在节流结束后
  • 手写一个节流函数来处理
    核心思路:利用定时器(setTimeout)来实现

例如:

<style>.box {width:500px;height:500px;background-color:#ccc;color:#fff;text-align:center;font-size:100px;}
</style>
<body><div class="box"></div><script src='./lodash.min.js'><script>// 利用节流实现性能优化// 需求:鼠标在盒子上移动,里面的数字就会变化+1const box = document.querySelector('.box')let i = 1function mouseMove() {box.innerHTML = i++// 如果里面存在大量消耗性能的代码,比如DOM操作、数据处理,可能造成卡顿}// 添加事件// box.addEventListener('mousemove',mouseMove)// 利用lodash库实现节流 500毫秒之后+1box.addEventListener('mousemove',_.throttle(mouseMove,500))// 手写函数部分// 1.声明一个定时器变量// 2.当鼠标每次滑动都先判断是否有定时器,如果有定时器则不开启新定时器// 3.如果没有定时器则开启定时器,记得存到变量里面// 3.1定时器里面调用执行的函数// 3.2定时器里面要把定时器清空function throttle(fn,t) {let timer = nullreturn function() {if(!timer) {timer = setTime(function() {fn()// 清空定时器// 在setTimeout中是无法删除定时器的,因为定时器还在运作,故不使用clearTimeront(timer)timer = null},t)}}}box.addEventListener('mousemove',throttle(mouseMove,500))</script>
</body>

相关文章:

JavaScript进阶-高阶技巧

文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变this 性能优化防抖节流 高阶技巧 深浅拷贝 只针对引用类型 浅拷贝 拷贝对象后&#xff0c;里面的属性值是简单数据类型直接拷贝值&#xff0c;如果属性值是引用数…...

C语言中“#“和“##“的用法

1. 前言 # &#xff1a;把宏参数变为一个字符串, ##&#xff1a;把两个宏参数贴合在一起. 2. 一般用法 #include<stdio.h> #define toString(str) #str //转字符串 #define conStr(a,b) (a##b)//连接 int main() { printf(toString(12345)): //输出字符串&q…...

Linux命令-clock命令(用于调整 RTC 时间)

说明 clock命令用于调整 RTC 时间。 RTC 是电脑内建的硬件时间&#xff0c;执行这项指令可以显示现在时刻&#xff0c;调整硬件时钟的时间&#xff0c;将系统时间设成与硬件时钟之时间一致&#xff0c;或是把系统时间回存到硬件时钟。 语法 clock [--adjust][--debug][--dir…...

编程笔记 Golang基础 045 math包

编程笔记 Golang基础 045 math包 一、math包主要功能常量&#xff1a;函数&#xff1a;数值运算&#xff1a;三角函数&#xff1a;对数函数&#xff1a;随机数相关&#xff1a; 二、示例代码一三、示例代码二小结 Go 语言的标准库 math 提供了一系列基础数学函数和常量&#xf…...

[Java 探索者之路] 一个大厂都在用的分布式任务调度平台

分布式任务调度平台是一种能够在分布式计算环境中调度和管理任务的系统&#xff0c;在此环境下&#xff0c;各个任务可以在独立的节点上运行。它有助于提升资源利用率&#xff0c;增强系统扩展性以及提高系统对错误的容忍度。 文章目录 1. 分布式任务调度平台1. 基本概念1.1 任…...

基于JAVA springboot+mybatis智慧生活分享平台设计和实现

基于JAVA springbootmybatis智慧生活分享平台设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末…...

详细了解C++中的namespace命名空间

键盘敲烂&#xff0c;月薪过万&#xff0c;同学们&#xff0c;加油呀&#xff01; 目录 键盘敲烂&#xff0c;月薪过万&#xff0c;同学们&#xff0c;加油呀&#xff01; 一、命名空间的理解 二、&#xff1a;&#xff1a;作用域运算符 三、命名空间&#xff08;namespace&…...

#WEB前端(HTML属性)

1.实验&#xff1a;a,img 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; a: href插入超链接 默认情况下在本窗口打开链接, target可以设置打开的窗口,parent在父窗口打开&#xff0c;blank新开串口打开,top在顶层串口打开,self为默认在本窗口打开 img: 插入图片 可以插…...

LeetCode---【和的操作】

目录 两数之和我的答案在b站up那里学到的【然后自己复写】 和为 K 的子数组在b站up那里学到的【然后自己复写】 三数之和在b站up那里学到的【然后自己复写】 两数相加【链表】我的半路答案&#xff1a;没有看到是链表在b站up那里学到的【复写失败后整理】 两数之和 我的答案 …...

Docker容器与虚拟化技术:OpenEuler 使用 docker-compose 部署 LNMP

目录 一、实验 1.环境 2.OpenEuler 部署 docker-compose 3.docker-compose 部署 LNMP 二、问题 1.ntpdate未找到命令 2.timedatectl 如何设置时区与时间同步 3.php网页显示时区不对 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注Lin…...

13-微服务初探-自研微服务框架

微服务初探 1. 架构变迁之路 1.1 单体架构 互联网早期&#xff0c;一般的网站应用流量较小&#xff0c;只需要一个应用&#xff0c;将所有的功能代码都部署在一起就可以&#xff0c;这样可以减少开发&#xff0c;部署和维护的成本。 比如说一个电商系统&#xff0c;里面包含…...

LeetCode——二叉树(Java)

二叉树 简介[简单] 144. 二叉树的前序遍历、94. 二叉树的中序遍历、145. 二叉树的后序遍历二叉树层序遍历[中等] 102. 二叉树的层序遍历[中等] 107. 二叉树的层序遍历 II[中等] 199. 二叉树的右视图[简单] 637. 二叉树的层平均值[中等] 429. N 叉树的层序遍历[中等] 515. 在每个…...

LDR6328芯片:智能家居时代的小家电充电革新者

在当今的智能家居时代&#xff0c;小家电的供电方式正变得越来越智能化和高效化。 利用PD&#xff08;Power Delivery&#xff09;芯片进行诱骗取电&#xff0c;为后端小家电提供稳定电压的技术&#xff0c;正逐渐成为行业的新宠。在这一领域&#xff0c;LDR6328芯片以其出色的…...

用node写后端环境运行时报错Port 3000 is already in use

解决方法:关闭之前运行的3000端口,操作如下 1.WindowR输入cmd确定,打开命令面板 2.查看本机端口详情 netstat -ano|findstr "3000" 3.清除3000端口 taskkill -pid 41640 -f 最后再重新npm start即可,这里要看你自己项目中package.joson的启动命令是什…...

Git 如何上传本地的所有分支

Git 如何上传本地的所有分支 比如一个本地 git 仓库里定义了两个远程分支&#xff0c;一个名为 origin&#xff0c; 一个名为 web 现在本地有一些分支是 web 远程仓库没有的分支&#xff0c;如何将本地所有分支都推送到 web 这个远程仓库上呢 git push web --all...

【airtest】自动化入门教程(一)AirtestIDE

目录 一、下载与安装 1、下载 2、安装 3、打开软件 二、web自动化配置 1、配置chrome浏览器 2、窗口勾选selenium window 三、新建项目&#xff08;web&#xff09; 1、新建一个Airtest项目 2、初始化代码 3、打开一个网页 四、恢复默认布局 五、新建项目&#xf…...

ChatGPT支持下的PyTorch机器学习与深度学习技术应用

近年来&#xff0c;随着AlphaGo、无人驾驶汽车、医学影像智慧辅助诊疗、ImageNet竞赛等热点事件的发生&#xff0c;人工智能迎来了新一轮的发展浪潮。尤其是深度学习技术&#xff0c;在许多行业都取得了颠覆性的成果。另外&#xff0c;近年来&#xff0c;Pytorch深度学习框架受…...

Springboot+vue的医药管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的医药管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…...

C语言:预处理

C语言&#xff1a;预处理 预定义符号#define定义常量定义宏宏与函数对比 #操作符##操作符条件编译头文件包含库文件包含本地文件包含嵌套文件包含 预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //…...

计算机网络:路由协议

路由协议简介 路由协议是计算机网络中不可或缺的一部分&#xff0c;它们负责确定数据包从源地址到目的地址的最佳路径。想象一下&#xff0c;如果你是一个数据包&#xff0c;路由协议就像是地图或导航工具&#xff0c;指导你如何到达目的地。 目录 路由协议简介 工作原理简化…...

Sourcetree实战指南:从零上手代码克隆、高效合并与冲突化解

1. 为什么你需要Sourcetree这款Git可视化工具 刚接触Git版本控制时&#xff0c;命令行操作总是让人望而生畏。记得我第一次用git merge时&#xff0c;不小心把同事的代码覆盖了&#xff0c;整个下午都在手忙脚乱地恢复文件。直到发现了Sourcetree这个神器&#xff0c;才真正体会…...

OpenCV中的VideoCapture后端参数详解城

智能体时代的代码范式转移与 C# 的战略转型 传统的 C# 开发模式&#xff0c;即所谓的“工程导向型”开发&#xff0c;要求开发者创建一个复杂的项目结构&#xff0c;包括项目文件&#xff08;.csproj&#xff09;、解决方案文件&#xff08;.sln&#xff09;、属性设置以及依赖…...

告别AD转Cadence的迷茫:OrCAD Capture CIS 16.6新建工程与环境设置保姆级指南

告别AD转Cadence的迷茫&#xff1a;OrCAD Capture CIS 16.6新建工程与环境设置保姆级指南 从Altium Designer切换到Cadence OrCAD&#xff0c;就像从自动挡汽车换到手动挡——虽然最终目的地相同&#xff0c;但操作方式截然不同。我至今记得第一次打开OrCAD时那种无处下手的窘迫…...

ElementUI下拉多选框避坑指南:如何优雅处理全选与反选逻辑

ElementUI多选框全选逻辑深度解析&#xff1a;从原理到最佳实践 下拉多选框是后台管理系统中最常用的交互组件之一&#xff0c;但很多开发者在实现全选功能时都会遇到各种边界问题。上周在重构供应链管理系统时&#xff0c;我花了整整两天时间才彻底解决了全选状态同步的难题—…...

组织熵增 vs AI原生熵减:用香农-组织信息论量化研发效能衰减(SITS2026首次发布行业基准值)

第一章&#xff1a;组织熵增 vs AI原生熵减&#xff1a;用香农-组织信息论量化研发效能衰减&#xff08;SITS2026首次发布行业基准值&#xff09; 2026奇点智能技术大会(https://ml-summit.org) 传统软件研发组织正面临不可逆的“组织熵增”——需求模糊度上升、接口契约漂移…...

LaserGRBL:5分钟掌握专业激光雕刻软件的核心技巧

LaserGRBL&#xff1a;5分钟掌握专业激光雕刻软件的核心技巧 【免费下载链接】LaserGRBL Laser optimized GUI for GRBL 项目地址: https://gitcode.com/gh_mirrors/la/LaserGRBL LaserGRBL是一款专为激光雕刻机设计的Windows图形界面软件&#xff0c;它基于开源的GRBL控…...

高性能无人机飞控系统源码:基于Cesium+Vue3+Vite的三维可视化平台

温馨提示&#xff1a;文末有联系方式1. 基于CesiumVue3Vite的现代化前端架构 采用轻量高效的技术栈构建——CesiumJS提供高精度地理空间渲染能力&#xff0c;Vue3带来响应式数据绑定与组合式API优势&#xff0c;Vite作为极速构建工具显著提升开发与部署体验&#xff0c;确保平台…...

宝塔面板7.7.0免费解锁专业版监控报表插件(附详细操作步骤)

宝塔面板7.7.0专业版监控报表插件深度解锁指南 在网站运维领域&#xff0c;数据可视化与实时监控已成为高效管理的标配。宝塔面板作为国内最受欢迎的服务器管理工具之一&#xff0c;其专业版的网站监控报表插件能提供精准的访问分析、蜘蛛抓取记录和流量统计功能。对于预算有限…...

【车载嵌入式】TBOX:智能汽车的“云端神经中枢”与数据引擎

1. TBOX&#xff1a;智能汽车的“云端神经中枢”是什么&#xff1f; 想象一下你的爱车突然有了“超能力”——能自动报告故障、远程启动空调、甚至预测保养时间。这些神奇功能的背后&#xff0c;都离不开一个藏在仪表盘下方的小盒子&#xff1a;TBOX&#xff08;Telematics BOX…...

高效CAJ转PDF工具:一站式解决学术文献格式转换难题

高效CAJ转PDF工具&#xff1a;一站式解决学术文献格式转换难题 【免费下载链接】caj2pdf Convert CAJ (China Academic Journals) files to PDF. 转换中国知网 CAJ 格式文献为 PDF。佛系转换&#xff0c;成功与否&#xff0c;皆是玄学。 项目地址: https://gitcode.com/gh_mi…...