浅拷贝和深拷贝
只针对引用数据类型
浅拷贝
简单数据类型拷贝值,引用数据类型拷贝地址(只适合单层)
方法:
1.拷贝对象:Object.assgin() 或 展开运算符{...obj}
2.拷贝数组:Array.prototype.concat() 或 [...arr]
const obj = {uname: 'pink',age: 18
}const o = {...obj}//不影响原对象
const obj = {uname: 'pink',age: 18
}const o = {}Object.assgin(o,obj)
但存在缺陷:
const obj = {uname: 'pink',age: 18,family: {baby:'小明'}
}const o = {}
Object.assign(o, obj)
o.family.baby='小明'console.log(o)
console.log(o)
更里层变量均发生改变
深拷贝
拷贝的是对象,而不是地址
方法:
1.递归方式实现深拷贝
2.lodash / cloneDeep
3.通过JSON.stringify()实现
递归函数
函数自己调用自己,由于容易栈溢出,必须添加退出条件 return
案例:
利用递归函数实现setTimeout模拟 setInterval效果
function getTime() {document.querySelector('div').innerHTML = new Date().toLocaleString()setTimeout(getTime, 1000)}getTime()
递归实现深拷贝
const obj = {uname: 'Tom',age: 18,sport: ['111', '222'],family: {son: 'Jack'}}const o = {}function deepCopy(newobj, oldobj) {for (let k in oldobj) {if (oldobj[k] instanceof Array) {//有Object不能放在前面,因为任何数据类型都是object,放在最后newobj[k] = []deepCopy(newobj[k], oldobj[k])} else if (oldobj[k] instanceof Object) {newobj[k] = {}deepCopy(newobj[k], oldobj[k])}else {newobj[k] = oldobj[k]}}}
lodash和JSON实现深拷贝
JSON方法:
const obj = {uname: 'Tom',age: 18,sport: ['111', '222'],family: {son: 'Jack'}}const o = json.parse(JSON.stringify(obj))
异常处理
throw抛异常
预估计代码执行过程中可能发生的错误,最大程度错误发生导致程序无法运行
1.throw抛出异常信息,程序也会终止
2.throw后跟着错误信息
3.和Error搭配,信息更详细
function fn(x){if(!x)
throw new Error('参数为空!')
}
try/catch 捕获异常信息
1.try...catch用于捕获错误信息
2.将预估可能发生的错误写在try代码中
3.try中代码错误,执行catch,截获错误信息
4.不管错没错,finally都会执行
debugger
类似打断点
在代码中写可以在操作台直接定位
this深入
this指向-普通函数
谁调用函数,this就指向谁
this指向-箭头函数
不受调用方式影响,箭头函数不存在this
箭头函数中this绑定的是最近作用域中的this,沿作用域链查找
DOM事件回调函数和原型对象中函数不建议使用箭头函数
因此我们可以改变this方向
call方法改变this方向
作用:
1.调用函数
2.改变this的值
语法: 函数名.call(this.Arg,arg1,arg2...)
thisArg:运行时指定this值
arg1,arg2是传递的其他参数
tt
const obj = {uname: 'Tom',age: 18,sport: ['111', '222'],family: {son: 'Jack'}}function fn(x, y) {}fn.call(obj, x, y)//fn的this指向obj,并调用了fn
apply()
语法: 函数名.apply(this.Arg,[arr])
[arr]: 传递的值必须在数组里
bind()
bind()不会调用函数,但会改变函数内部this指向
语法: 函数名.bind(this.Arg,arg1,arg2...)
返回 指定this值和初始化参数改造的原拷贝函数
const obj = {}function fn() {}const fun = fn.bind()//返回对原函数的拷贝,但this值发生变化
fun()
比如定时器内部this指向
const btn = document.querySelector('button')btn.addEventListener('click', function () {this.disabled = turewindow.setTimeout(function () {this.disabled = false}.bind(this), 2000)//this指向变化})
防抖及其底层
防抖(debounce):单位时间内,频繁触发事件,只执行最后一次
缓冲时间段再次执行会取消上一次执行,防止消耗性能
案例:鼠标滑动,数字增加(停止500ms数字才会增加)
lodashjs库方法:
const box = document.querySelector('.box')let i = 1function move() {box.innerHTML = i++}box.addEventListener('mousemove', _.debounce(move, 500))//防止太过消耗性能
底层:
防抖的核心是定时器(setTimeout)实现
在定时器内执行代码,在特定条件下取消定时器
const box = document.querySelector('.box')let i = 1function move() {box.innerHTML = i++}function debounce(fn, t) {//返回函数,否则会立即执行let timerreturn function () {if (timer) clearTimeout(timer)timer = setTimeout(function () {fn()}, t)}}box.addEventListener('mousemove', debounce(move, 500))
节流
一段时间内只能触发一次
案例:
const box = document.querySelector('.box')let i = 1function move() {box.innerHTML = i++}function throttle(fn, t) {//返回函数,否则会立即执行let timerreturn function () {if (!timer)timer = setTimeout(function () {fn()timer = null}, t)}}box.addEventListener('mousemove', throttle(move, 500))
防抖与节流的区别
防抖:单位时间频繁触发,只执行最后一次,电话号码输入检测
节流:单位时间高频触发,只执行一次,mousemove