沧州哪里可以做网站,广西南宁市有哪些网络公司,高清视频素材,凡科网建立网站后怎么修改文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变this 性能优化防抖节流 高阶技巧
深浅拷贝
只针对引用类型
浅拷贝
拷贝对象后#xff0c;里面的属性值是简单数据类型直接拷贝值#xff0c;如果属性值是引用数… 文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变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
scriptconst obj {uname:pink,age:18,hobby:[乒乓球,足球],family:{baby:xiaop}}const o _.cloneDeep(obj)o.family.baby oldpconsole.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值 arg1arg2传递的其他参数 返回值就是函数的返回值因为它就是调用函数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)// 3bind()重点 bind()方法不会调用函数但是能改变函数内部this指向 语法fn.bind(thisArg,arg1,arg2...) thisArg在fn函数运行时指定的this的值 arg1arg2传递的其他参数 返回由指定的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}bodybutton发送/buttonscript// 需求有一个按钮点击里面就禁用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,[wait0],[options]) func要防抖的函数 [wait0]需要延迟的毫秒数 [options]选项对象手写防抖函数 核心思路利用定时器setTimeout来实现
例如
style.box {width:500px;height:500px;background-color:#ccc;color:#fff;text-align:center;font-size:100px;}
/style
bodydiv classbox/divscript src./lodash.min.jsscript// 利用防抖实现性能优化// 需求鼠标在盒子上移动里面的数字就会变化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,[wait0],[options]) func要节流的函数 [wait0]需要节流的毫秒数 [options]选项对象 [options.leadingtrue]指定调用在节流开始前 [options.leadingfalse]指定调用在节流结束后手写一个节流函数来处理 核心思路利用定时器setTimeout来实现
例如
style.box {width:500px;height:500px;background-color:#ccc;color:#fff;text-align:center;font-size:100px;}
/style
bodydiv classbox/divscript src./lodash.min.jsscript// 利用节流实现性能优化// 需求鼠标在盒子上移动里面的数字就会变化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