JavaScript进阶-高阶技巧
本章为JavaScript进阶篇的最后一章,我们会总结一些JavaScript中的常见技巧,这些技巧可以帮助我们写出更加简洁、优雅的代码。
深浅拷贝(引用类型)
为什么在小标题中说引用类型,因为基本类型不存在深浅拷贝的问题,他们在栈中就存储真实数据,而引用类型在栈中存储地址,在堆中存储真实数据,所以才有深浅拷贝的区分。
浅拷贝
浅拷贝指的是只复制地址,没有产生新的对象,所以修改新对象会影响到原对象。
浅拷贝的实现方式有很多,比如:
1 | // 1. Object.assign |
在这里笔者不一一列举浅拷贝的实现方式,感兴趣的读者可以自行查阅资料。
深拷贝
深拷贝指的是复制对象,产生新的对象,修改新对象不会影响到原对象。
深拷贝的实现方式也有很多,比如:
lodash包的cloneDeep方法JSON.stringify()方法实现:const newObj = JSON.parse(JSON.stringify(obj)),但是这样会遇到循环引用问题。- 递归实现:这里需要结合我们在原型章节中学到的
instanceof方法来判断是否为对象,然后递归调用,具体实现如下:
1 | const person = { |
异常处理
这个比较简单,如果有其他编程语言基础的读者一定不会陌生:
throw抛异常:throw new Error('错误信息')。try/catch捕获异常:try中书写可能出现错误的代码;catch捕获对应try块中发生的异常并处理;finally是无论是否发生异常、catch有没有返回,都会执行的代码。debugger关键字:这是JavaScript中一个特殊的调试关键字,当代码执行到这个关键字时,会自动暂停,并进入调试模式,方便我们查看代码执行情况。
处理this
我们先来复习一下this的指向问题:
- 普通函数this指向:谁调用this就指向谁。
- 箭头函数this指向:函数内没有this,沿用上一级的this。
那么我们如果想要指定this的指向呢?Function.prototype上提供了三个方法可以指定this的指向: fun.call(thisArg, arg1, arg2, ..., argN):使用call方法调用函数,同时thisArg指定this指向。fun.apply(thisArg, [argsArr]):使用apply方法调用函数,thisArg指定this指向,参数传递必须以数组形式传递。- 应用场景:求数组最大值
Math.max.apply(Math, arr)。
- 应用场景:求数组最大值
fun.bind(thisArg, arg1, arg2, ...):不会调用函数,能改变函数内this指向,返回由指定的this值和初始化参数改造的原函数拷贝。- 使用场景:只想改变this指向,不想调用函数时。
性能优化
在实际开发场景中,我们需要非常注重性能问题,良好的性能可以提升用户的体验,下面将介绍实际开发过程中常见的两种性能优化手段:
- 防抖:单位时间内,频繁触发事件,只执行最后一次。
- 使用场景:搜索框输入;手机号、邮箱输入验证。
lodash实现:_.debounce(func, 毫秒)。- 手写实现:利用定时器
setTimeout,声明一个定时器变量,每当事件触发都先判断是否有定时器,如果有就清除以前的定时器,如果没有就开启定时器存入变量,在定时器里调用要执行的函数。
1 | function debounce(func, time){ |
- 节流:单位时间内频繁触发事件,只执行一次
- 使用场景:鼠标移动
mousemove,页面尺寸缩放resize,滚动条滚动scroll。 lodash实现:_.throttle(func, 毫秒)。- 手写实现:利用定时器实现,声明一个定时器变量,每当事件触发都先判断是否有定时器,如果有则不开启新定时器,如果没有定时器则开启定时器并存入变量(定时器里调用执行的函数,定时器结束时要清空定时器)。
- 使用场景:鼠标移动
1 | function throttle(func, time){ |
总结
本章我们总结了JavaScript中的一些常见技巧,这些技巧可以帮助我们写出更加简洁、优雅的代码。至此,JavaScript进阶篇就结束了,希望读者能够有所收获。后续我们将继续学习Web API的相关操作。