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

JavaScript 进阶(面试必备)--charater4


文章目录

  • 前言
  • 一、深浅拷贝
    • :one: 浅拷贝
    • :two:深拷贝
  • 二、异常处理
    • :one: throw 抛异常
    • :two: try /catch 捕获异常
    • :three:debugger
  • 三、处理this
    • `this指向` :one:普通函数this指向
    • `this指向` :two: 箭头函数this指向
    • 3.2 改变this
      • :one: call()
      • :two: apply()
      • :three: bind()
  • 四、性能优化
    • :one: 节流 throttle
    • :two:防抖 debounce
  • 总结


前言

这章学习目标:

  1. 深入this学习,知道如何判断this指向和改变this 指向
  2. 知道在JS中如何处理异常,学习深浅拷贝,理解递归。

提示:以下是本篇文章正文内容,下面案例可供参考

一、深浅拷贝

1️⃣ 浅拷贝

对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是对两个对象指向同一个地址,修改其中一个对象的属性,则另外一个对象的属性也会改变。简单的来说,拷贝的是地址。
在这里插入图片描述
🔴拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
🔴如果属性值是引用数据类型则拷贝的是地址

// 一个pink对象
const pink ={name:'pink老师'age:18
}
const red = pink
console.log(red)//{name:'pink老师',age:18}red.name='red老师'
console.log(red)//{name:'red者师',age:18}
//但是pink对象里面的name值也发生了变化
console.log(pink)//[name:'red老师',age:18}

⭕️常用方法
🕐拷贝对象:Object.assign() 或者展开符 {…obj } 拷贝对象

  const obj = {uname: 'pink',age: 18}const o = objconsole.log("o",o)o.age = 20console.log(" o.age",o)console.log("obj",obj)
 const obj = {uname: 'pink',age: 18}const o = {}Object.assign(o, obj)o.age = 20o.family.baby = '老pink'console.log(o)console.log(obj)

在这里插入图片描述
🕑拷贝数组:Array.prototype.concat() 或者[…arr]

✅ 直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址。

✅ 浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响,

2️⃣深拷贝

⭕️ 常见方法:

  1. 通过递归实现深拷贝
    如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
    🆔递归函数的作用和循环效果类似
    🆔由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
    在这里插入图片描述
    let i = 1function fn() {console.log(`这是第${i}`)if (i >= 6) {return}i++fn()// 函数内部调用自己}fn()

2. js库lodash 里clone Deep内部实现深拷贝

  <!-- 先引用 --><script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = _.cloneDeep(obj)console.log(o)o.family.baby = '老pink'console.log(obj)

在这里插入图片描述
3. 通过JSON.stringify()实现

    const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}// 把对象转换为 JSON 字符串// console.log(JSON.stringify(obj))const o=JSON.parse(JSON.stringify(obj))console.log(o)o.family.baby = '123'console.log(obj)

在这里插入图片描述

二、异常处理

1️⃣ throw 抛异常

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

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

function counter(x,y){if(!x||!y){throw new Error('参数不能为空')}return x+y
}
counter()

2️⃣ try /catch 捕获异常

  1. try…catch 用于捕获错误信息。
  2. 将预估可能发生错误的代码写在 try 代码段中。
  3. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息
  4. finally 不管是否有错误,都会执行。
   function fn() {try {// 可能预估有问题的代码写到这里const p = document.querySelector('.p')p.style.color = 'red'} catch (err) {console.log(err.message)// 中断// returnthrow new Error('你是不是把选择器写错了')} finally {alert('执行')} console.log(111)}fn()

3️⃣debugger

我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息)
在这里插入图片描述

三、处理this

不同的应用场合 this 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。知道动态指定函数 this 值的方法。

this指向 1️⃣普通函数this指向

普通函数的调用方法决定了this的值,即【谁调用this 就指向谁】

 // 普通函数:  谁调用我,this就指向谁
1. console.log(this)  // windowfunction fn() {console.log(this)  // window    }window.fn()window.setTimeout(function () {console.log(this) // window }, 1000)2.document.querySelector('button').addEventListener('click', function () {console.log(this)  // 指向 button})3.const obj = {sayHi: function () {console.log(this)  // 指向 obj}}obj.sayHi()

this指向 2️⃣ 箭头函数this指向

箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this

  1. 箭头函数会默认帮我们绑定外层this的值,所有在箭头函数中this的值和外层this是一样的
  2. 箭头函数中的this引用的就是最近作用域中的this
  3. 向外层作用域中,一层一层查找this,直到有this的定义
1.console.1og(this)//此处为window
//箭头函数
const sayHi = function(){console.log(this)//该箭头函数中的this为函数声明环境中this一致
}2.    //普通对象
const user={name:'小明',//该箭头函数中的this为函数声明环境中this一致walk:()=>{console.log(this)}
}

👿【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this为全局的window 因此DOM 事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数

//D0M 节点
const btn=document.queryselector('.btn')
//箭头函数此时this指向了window
btn.addEventListener('click',()=>console.log(this)
})//普通函数此时this指向了DoM对象
btn.addEventListener('click',function (){console.log(this)
})

😈同样由于this的原因,原型的对象不推荐采用箭头函数。

  1. 函数内不存在this,沿用上一级的this
  2. 不适应构造函数,原型函数,dom事件函数等等。
  3. 需要用上层this的地方。

3.2 改变this

JavaScript 允许指定函数中this 的指向,有3个方法可以动态指定普通函数中 this 的指向

1️⃣ call()

使用call 方法调用函数,同时指定被调用函数中 this 的值。

fun.call(thisArg, arg1, arg2, ...)

thisArg:在fun 函数运行时指定的this
arg1,arg2:传递参数
返回值就是函数的返回值,因为它就是调用函数。

    const obj = {uname: 'pink'}function fn(x, y) {console.log(this) // window.objectconsole.log(x + y)// 3}// 1. 调用函数  // 2. 改变 this 指向fn.call(obj, 1, 2)

2️⃣ apply()

使用 apply 方法调用函数,同时指定被调用函数中 this 的值。

  1. 调用函数
    2. 改变this指向
 fn.apply(this指向谁, [数组参数])
    const obj = {age: 18}function fn(x, y) {console.log(this) // Object{age: 18}console.log(x + y)// 3}fn.apply(obj, [1, 2])//  返回值   本身就是在调用函数,所以返回值就是函数的返回值

thisArg:在fun函数运行时指定的 this 值
argsArray:传递的值,必须包含在数组里面
返回值就是函数的返回值。因为它就是调用函数
apply 主要跟数组有关系,比如使用Math.max() 求数组的最大值。

1.const max = Math.max(1,2,3)
2.const arr =[100 , 45 ,55]
const max =Math.math.apply(Math,arr)
const min =Math.math.apply(Matg,arr)
console.log(max,min)
3. console.log(Math.max(...arr))

3️⃣ bind()

bind() 方法不会调用函数,但是能改变函数内部this 指向。

fun.bind(thisArg, arg1, arg2, ...)

thisArg:在 fun 函数运行时指定的 this 值
arg1,arg2:传递的其他参数
返回由指定的this 值和初始化参数改造的 原函数
如果不想调用函数来改变this指向时,可以使用bind,比如改变定时器内部的this 指向

  // 普通函数function sayHi() {console.log(this)}let user = {name: '小明',age: 18}// 调用 bind 指定 this 的值let sayHello = sayHi.bind(user);// 调用使用 bind 创建的新函数sayHello()

🔥注:bind 方法创建新的函数,与原函数的唯一的变化是改变了 this 的值。

四、性能优化

1️⃣ 节流 throttle

节流就指连续触发事件但是在n秒中只执行一次函数。就如等到上一个人完成动作,才能进行下一个人执行。
开发使用场景小米轮播图点击效果鼠标移动页面尺寸缩放resize滚动条滚动 就可以加节流。
如果一张轮播图完成切换需要300ms,不加节流效果,快速点击,就会快速切换。

2️⃣防抖 debounce

防抖就是触发事件后在n秒内函数只能执行一次,如果在n秒内再次触发事件,则会重新计算

开发使用场景- 搜索框防抖
假设输入就可以发送请求,但是不能每次输入都去发送请求,输入比较快发送请求会比较多,我们设定一个时间,假如300ms, 当输入第一个字符时候,300ms后发送请求,但是在200ms的时候又输入了一个字符,则需要再等300ms 后发送请求。

总结

本章深入学习里this学习,知道如何判断this指向和改变this指向,深浅拷贝,递归等知识点,在面试备考中希望能帮助到大家❤️

相关文章:

JavaScript 进阶(面试必备)--charater4

文章目录前言一、深浅拷贝:one: 浅拷贝:two:深拷贝二、异常处理:one: throw 抛异常:two: try /catch 捕获异常:three:debugger三、处理thisthis指向 :one:普通函数this指向this指向 :two: 箭头函数this指向3.2 改变this:one: call():two: apply():three: bind()四、性能优化:on…...

ARM+FPGA架构开发板PCIE2SCREEN示例分析与测试-米尔MYD-JX8MMA7

本篇测评由电子发烧友的优秀测评者“zealsoft”提供。 本次测试内容为米尔MYD-JX8MMA7开发板其ARM端的测试例程pcie2screen并介绍一下FPGA端程序的修改。 ​ 01. 测试例程pcie2screen 例程pcie2screen是配合MYD-JX8MMA7开发板所带的MYIR_PCIE_5T_CMOS 工程的测试例&#…...

51单片机入门 - SDCC / Keil_C51 会让没有调用的函数参与编译吗?

Small Device C Compiler&#xff08;SDCC&#xff09;是一款免费 C 编译器&#xff0c;适用于 8 位微控制器。 不想看测试过程的话可以直接划到最下面看结论&#xff1a;&#xff09; 关于软硬件环境的信息&#xff1a; Windows 10STC89C52RCSDCC &#xff08;构建HEX文件&…...

OpenCV只含基本图像模块编译

编译OpenCV4.5.5只含基本图像模块&#xff0c;环境为Windows10 x64CMake3.23.3VS2019。默认编译选项编译得到的OpenCV库往往大几百MB甚至上GB&#xff0c;本文配置下编译得到的库压缩后得到的zip包大小仅6.25MB&#xff0c;适合使用OpenCV基本图像功能模块的项目移植而不牵涉其…...

Java实现阴历日历表(附带星座)

准备工作 1.无敌外挂(GitHub直达源码) Nobb 直击灵魂 https://github.com/xuyishanBD/Java_create_calendar.git2.maven配置(如果没有走上面的捷径) <dependencies><dependency><groupId>net.sourceforge.javacsv</groupId><artifactId>javac…...

Python入门之最基础

Python入门之最基础 IDLE有两种模式&#xff0c;一种是交互模式&#xff0c;通俗讲就是写一个代码&#xff0c;会得到相应的反馈&#xff0c;另一种为编辑模式. 注意事项&#xff1a; 标点符号一定要用英文符号 要注意缩进 dir(builtins)可以看到python所有的内置函数&#…...

浏览器缓存策略

先走强缓存&#xff0c;再走协商缓存 强缓存 不发送请求&#xff0c;直接使用缓存的内容 状态码200 当前会话没有关闭的话就是走memory cache&#xff0c;否则就是disk cache 由响应头的 Pragma&#xff08;逐渐废弃&#xff0c;优先级最高&#xff09;&#xff0c;catch-…...

高清无码的MP4如何采集?python带你保存~

前言 大家早好、午好、晚好吖 ❤ ~ 又是我,我又来采集小姐姐啦~ 这次我们采集的网站是(看下图): 本文所有模块\环境\源码\教程皆可点击文章下方名片获取此处跳转 话不多少,我们赶快开始吧~ 第三方模块: requests >>> pip install requests 如果安装python第三方模块…...

python+pytest接口自动化(1)-接口测试基础

接口定义一般我们所说的接口即API&#xff0c;那什么又是API呢&#xff0c;百度给的定义如下&#xff1a;API&#xff08;Application Programming Interface&#xff0c;应用程序接口&#xff09;是一些预先定义的接口&#xff08;如函数、HTTP接口&#xff09;&#xff0c;或…...

go单元测试

接着上一篇中的go module创建项目calc为例&#xff0c;在simplemath包中&#xff0c;是使用在命令行中使用交互式的方式进行测试&#xff0c;现在可以为这几个函数实现单元测试&#xff0c; go test&#xff0c;这个测试工具来自于 Go 官方的 gc 工具链。 运行 go test 命令将执…...

Mybatis之一级缓存二级缓存

介绍 缓存&#xff0c;就是将经常访问的数据&#xff0c;放到内存中&#xff0c;减少对数据库的访问&#xff0c;提高查询速度。Mybatis中也有缓存的概念&#xff0c;分为一级缓存和二级缓存。 一级缓存 一级缓存是Mybatis中SqlSession对象的缓存。当我们执行查询以后&#x…...

人脸考勤机项目

文章内容如下&#xff1a; 1&#xff09;项目简介 2&#xff09;开发环境和使用的技术知识 3&#xff09;功能实现 4&#xff09;项目源码 一。项目简介 此项目是基于HOG和Dlib开发的一套实时无感考勤系统。首先是待考勤人员的个人信息录入。然后在过道或者入口处装置人脸…...

Python编程自动化办公案例(3)

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.前几章代码 1.获取到第一题的选项单元格 2.实现批量获取文件 二. 批…...

Linux-MYSQL 登录数据库(命令行,图形化) 及 远程登录

命令行登录 &#xff1a;mysql 命令登录数据库语法 &#xff1a; mysql -u用户名 -p密码 -h 连接的数据库服务器的ip [-D] 数据库名 -p 端口注 &#xff1a; 上面的 mysql 命令是指的是 客户端的指令 ~&#xff01;&#xff01;-h &#xff1a; 指的就是 连接数据库服务器的 ip…...

electron网络环境在线/离线事件探测

electron判断网络环境问题&#xff0c;可以说在任何桌面应用都可以使用到&#xff0c;处理方式有很多种&#xff0c;我介绍几种办法第一种HTML5 API navigator.onLine&#xff1a;官方案例给的&#xff0c;这边为直接贴出地址了&#xff0c;有兴趣的同学可自行查看https://www.…...

UE 项目导航数据生成配置

WP构建及常规构建操作WP构建方式 &#xff1a;https://docs.unrealengine.com/5.0/zh-CN/world-partitioned-navigation-mesh/常规构建方式针对WP的构建方式特殊配置项关闭就好&#xff1a;取消勾选RecastNavMesh-XXX下的IsWorldPartitioned执行n.bNavMeshAllowPartitionedBuil…...

494.目标和

1. 回溯算法 这题和之前做的那些排列、组合的回溯稍微有些不同&#xff0c;你不需要每次选数据时都是for遍历去选择&#xff0c;很明显这是顺序选择的 比如 数组[0,1]&#xff0c;target1&#xff1b; 递归数组&#xff0c;每个元素都 或者 - &#xff0c;然后取最后结果为0…...

滑台模组的应用有哪些?

在自动化生产中&#xff0c;我们常常会看到滑台模组的身影&#xff0c;那么&#xff0c;滑台模组究竟在自动化生产设备中起着怎样的作用呢&#xff1f; 简单点说&#xff0c;滑台模组由滑块、滚珠丝杆、导轨、主体等其它传动零件组成的自动化晋级单元&#xff0c;经过各单元的组…...

CS224W课程学习笔记(四):node2vec算法原理与说明

引言 什么是图嵌入&#xff1f; 我想从上节的deepwalk中已经有一个十分完整的轮廓了&#xff0c;这里引出deepwalk论文中的一张很形象的图&#xff08;当然&#xff0c;上节的一些实战演练&#xff0c;也将这种嵌入关系进行了模拟与可视化&#xff0c;前文为&#xff1a;&…...

扩展lucas定理

前置知识&#xff1a; lucas定理中国剩余定理 介绍 当正整数n,mn,mn,m很大&#xff0c;且质数ppp较小的时候&#xff0c;要求CnmC_n^mCnm​对ppp取模后的值&#xff0c;可以用lucas定理。 但如果ppp不是质数&#xff0c;那该怎么办呢&#xff1f;如果mmm较小&#xff0c;则…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...