网站建设后期需要后期做的,合肥建设干部学校网站,国内团购网站做的最好的是,网站仿站大多少钱目录 深浅拷贝
浅拷贝
深拷贝
递归实现深拷贝
js库lodash里面cloneDeep内部实现了深拷贝
JSON序列化
异常处理 throw 抛异常
try /catch 捕获异常
debugg
处理this
this指向
普通函数
箭头函数
改变this
call()
apply()
bind()
call apply bind 总结
性能优化…
目录 深浅拷贝
浅拷贝
深拷贝
递归实现深拷贝
js库lodash里面cloneDeep内部实现了深拷贝
JSON序列化
异常处理 throw 抛异常
try /catch 捕获异常
debugg
处理this
this指向
普通函数
箭头函数
改变this
call()
apply()
bind()
call apply bind 总结
性能优化
防抖
节流 深浅拷贝
浅拷贝
首先浅拷贝和深拷贝只针对引用类型
浅拷贝拷贝的是地址
常见方法
拷贝对象Object.assgin() / 展开运算符 {...obj} 拷贝对象拷贝数组Array.prototype.concat() 或者 [...arr] 如果是简单数据类型拷贝值引用数据类型拷贝的是地址 (简单理解 如果是单层对象没问题如果有多层就有问题) 深拷贝
首先浅拷贝和深拷贝只针对引用类型
深拷贝拷贝的是对象不是地址
常见方法
通过递归实现深拷贝lodash/cloneDeep通过JSON.stringify()实现 递归实现深拷贝
怎么实现深拷贝
拷贝出来的新对象不会影响旧对象要用到函数递归实现遇到普通的拷贝直接赋值如果遇到数组的再次调用递归函数如果遇到 对象形式 再次利用递归解决先数组再对象
函数递归
如果一个函数在内部可以调用其本身那么这个函数就是递归函数
简单理解:函数内部自己调用自己, 这个函数就是递归函数递归函数的作用和循环效果类似由于递归很容易发生“栈溢出”错误stack overflow所以必须要加退出条件 return
bodyscriptconst obj {uname: pink,age: 18,hobby: [乒乓球, 足球],family: {baby: 小pink}}const o {}// 拷贝函数function deepCopy(newObj, oldObj) {debuggerfor (let k in oldObj) {// 处理数组的问题 一定先写数组 在写 对象 不能颠倒if (oldObj[k] instanceof Array) {newObj[k] []// newObj[k] 接收 [] hobby// oldObj[k] [乒乓球, 足球]deepCopy(newObj[k], oldObj[k])} else if (oldObj[k] instanceof Object) {newObj[k] {}deepCopy(newObj[k], oldObj[k])}else {// k 属性名 uname age oldObj[k] 属性值 18// newObj[k] o.uname 给新对象添加属性newObj[k] oldObj[k]}}}deepCopy(o, obj) // 函数调用 两个参数 o 新对象 obj 旧对象console.log(o)o.age 20o.hobby[0] 篮球o.family.baby 老pinkconsole.log(obj)console.log([1, 23] instanceof Object)// 复习// const obj {// uname: pink,// age: 18,// hobby: [乒乓球, 足球]// }// function deepCopy({ }, oldObj) {// // k 属性名 oldObj[k] 属性值// for (let k in oldObj) {// // 处理数组的问题 k 变量// newObj[k] oldObj[k]// // o.uname pink// // newObj.k pink// }// }/script
/body
js库lodash里面cloneDeep内部实现了深拷贝 !-- 先引用 --script src./lodash.min.js/script
再调用const o _.cloneDeep(obj)
JSON序列化 通过JSON.stringify()实现 JSON.parse实现 bodyscript// 把对象转换为 JSON 字符串// console.log(JSON.stringify(obj))//把字符串 用parse 转为对象 形成新对象const o JSON.parse(JSON.stringify(obj))console.log(o)o.family.baby 123console.log(obj)/script
/body 异常处理 throw 抛异常
异常处理是指预估代码执行过程中可能发生的错误然后最大程度的避免错误的发生导致整个程序无法继续运行
总结
throw 抛出异常信息程序也会终止执行throw 后面跟的是错误提示信息Error 对象配合 throw 使用能够设置更详细的错误信息
try /catch 捕获异常
总结
try...catch 用于捕获错误信息将预估可能发生错误的代码写在 try 代码段中如果 try 代码段中出现错误后会执行 catch 代码段并截获到错误信息 finally 不管是否有错误都会执行
debugg
相当于断点调试 处理this
this指向
普通函数
普通函数的调用方式决定了 this 的值即【谁调用 this 的值指向谁】
注 普通函数没有明确调用者时 this 值为 window严格模式下没有调用者时 this 的值为 undefined
箭头函数
箭头函数中的 this 与普通函数完全不同也不受调用方式的影响事实上箭头函数中并不存在 this 箭头函数中访问的 this 不过是箭头函数所在作用域的 this 变量。 改变this call()
使用 call 方法调用函数同时指定被调用函数中 this 的值
语法fun.call(thisArg, arg1, arg2, ...)
总结
call 方法能够在调用函数的同时指定 this 的值使用 call 方法调用函数时第1个参数为 this 指定的值call 方法的其余参数会依次自动传入函数做为函数的参数
apply()
使用 apply 方法调用函数同时指定被调用函数中 this 的值 语法 fun.apply(thisArg, [argsArray]) 总结 apply 方法能够在调用函数的同时指定 this 的值使用 apply 方法调用函数时第1个参数为 this 指定的值apply 方法第2个参数为数组数组的单元值依次自动传入函数做为函数的参数 因此 apply 主要跟数组有关系比如使用 Math.max() 求数组的最大值 bind()
bind 方法并不会调用函数而是创建一个指定了 this 值的新函数 语法 fun.bind(thisArg, arg1, arg2, ...) 返回由指定的 this 值和初始化参数改造的 原函数拷贝 新函数 因此当我们只是想改变 this 指向并且不想调用这个函数的时候可以使用 bind比如改变定时器内部的 this指向 注bind 方法创建新的函数与原函数的唯一的变化是改变了 this 的值。
call apply bind 总结 相同点: 都可以改变函数内部的this指向. 区别点: call 和 apply 会调用函数, 并且改变函数内部this指向. call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2..形式 apply 必须数组形式[arg] bind 不会调用函数, 可以改变函数内部this指向. 主要应用场景: call 调用函数并且可以传递参数 apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值 bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向 性能优化 防抖
防抖debounce 所谓防抖就是指触发事件后在 n 秒内函数只能执行一次如果在 n 秒内又触发了事件则会重新计算函数执行时间 开发使用场景- 搜索框防抖 scriptconst box document.querySelector(.box)let i 1 // 让这个变量// 鼠标移动函数function mouseMove() {box.innerHTML i// 如果里面存在大量操作 dom 的情况可能会卡顿}// 防抖函数function debounce(fn, t) {let timeIdreturn function () {// 如果有定时器就清除if (timeId) clearTimeout(timeId)// 开启定时器 200timeId setTimeout(function () {fn()}, t)}}// box.addEventListener(mousemove, mouseMove)box.addEventListener(mousemove, debounce(mouseMove, 200))/script
防抖函数怎么实现 核心就是利用setTimeout定时器来实现
1、声明定时器变量
2、每次触发时间都要判断是否有定时器 如果有就先清除以前的定时器
3、如果没有定时器 则开启定时器 存到定时器变量里面
4、定时器里面写函数调用 节流 节流throttle 所谓节流就是指连续触发事件但是在 n 秒中只执行一次函数 const box document.querySelector(.box)let i 1 // 让这个变量// 鼠标移动函数function mouseMove() {box.innerHTML i// 如果里面存在大量操作 dom 的情况可能会卡顿}// console.log(mouseMove)// 节流函数 throttle function throttle(fn, t) {// 起始时间let startTime 0return function () {// 得到当前的时间let now Date.now()// 判断如果大于等于 500 采取调用函数if (now - startTime t) {// 调用函数fn()// 起始的时间 现在的时间 写在调用函数的下面 startTime now}}}box.addEventListener(mousemove, throttle(mouseMove, 500)) script src./lodash.min.js/scriptscriptconst box document.querySelector(.box)let i 1 // 让这个变量// 鼠标移动函数function mouseMove() {box.innerHTML i// 如果里面存在大量操作 dom 的情况可能会卡顿}// box.addEventListener(mousemove, mouseMove)// lodash 节流写法// box.addEventListener(mousemove, _.throttle(mouseMove, 500))// lodash 防抖的写法box.addEventListener(mousemove, _.debounce(mouseMove, 500))/script