前言
分享即学习,欢迎转载,随意抄袭,学到了就是你的。
- 文章共分成两个部分,分别为js部分与html+css部分。
- 本文针对js优化部分,后续会跟进html+css部分。
- 纯手码内容较长,建议分开食用,下面会先呈上目录。
正文
js优化建议
首先说明,本文仅供优化的方向和思路,会举例说明,并不代表所有的语法都要这么写,要结合应用场景与当前开发团队的平均水平,合理使用,而不是一味追求优化而去要求团队的代码风格,如果非要追求代码的统一性,也应该把业务处理或数据处理的方法变成共通方法,让开发人员调用。
在没有足够的时间和经验以及项目积累的情况下,时刻谨记,按时完成任务才是关键,完成任务是主优化代码其次。
js优化方向
提到优化,大多数想到的场景都是性能优化。
以前,由于浏览器以及网速的限制,代码性能优化就显得极为重要。
但在如今,谷歌浏览器独步天下已成必然,网速更是直线飞起,互联网产品的版本更新迭代更加频繁。
所以,应该适度考虑牺牲一点点性能,而去做代码层次的优化。
语义清晰、逻辑明了的代码既可以增强开发效率,同时也更利于增强代码的可读性、降低维护成本、版本迭代更新。
恰到好处的高级函数使用才是对于前端代码优化的最好方向,而不是一味地追求性能。
js优化建议
言归正传,优化的思路主要考虑以下4点:
- 语义简单明了,逻辑清晰且合理
- 合理使用高级函数
- 方法尽早返回、尽早结束
- 减少运算、 减少语句
满足以上四点,哪怕不做性能优化,也能保证代码的执行效率。
举例:
众所周知,就性能而言for > map
在网上可能都看过这样的测试
let test = 99999
let arr = new Array(33333333).fill(test)
console.time()
// 原生for
for (let i = 0; i < arr.length; i++) {}
// map
arr.map((item, index, arr) => {})
console.timeEnd()
电脑配置i7-9750H测试结果
for 18ms左右
map 420-480ms
乍一看相差确实很大,但是现实中使用的场景却不可能是这样的,肯定是带着运算和数据处理的,看下面的例子:
console.time()
let test = 9999999
let arr = new Array(9999999).fill(test)
let arrayList = []
// 原生for
for (let i = 0; i < arr.length; i++) {
arrayList.push(arr[i])
}
// map
let arrayList = arr.map(item => item)
console.timeEnd()
电脑配置i7-9750H测试结果
for 705-720ms左右
map 680-700ms左右
结果map还比for快。单单论性能而言,肯定是for更快,但是写for方法的时候多了很多运算比如arr.length、push在每次循环时都执行。
所以,不论是考虑代码的性能还是、可读性,合理的使用高级函数才对代码的最好优化。
以判断语句为例,优化之时应考虑以下几点:
- 更少的嵌套,尽早返回,错误语句应提前抛出,使用return或throw
- 就性能而言:当数据量达到万级以上,if的执行速度反而会比switch更快;
- 正常逻辑判断数量不会超过两位数,所以应选择合适的实现方式;
- if在某些情景更适合表达逻辑,witch的控制表达式会依次与case后的值匹配,可以根据case标签的执行频率排列case标签的顺序进一步提高速度。
// bad
if (color) {
if (color === 'black') {
printBlackBackground();
} else if (color === 'red') {
printRedBackground();
} else if (color === 'blue') {
printBlueBackground();
} else if (color === 'green') {
printGreenBackground();
} else {
printYellowBackground();
}
}
// good
var colorObj = {
'black': printBlackBackground,
'red': printRedBackground,
'blue': printBlueBackground,
'green': printGreenBackground,
'yellow': printYellowBackground
}
if (color in colorObj) {
colorObj[color]()
}
// bad
function condition(fruit) {
if (fruit == 'apple' || fruit == 'banana') {
console.log(fruit);
}
}
// good
function condition(fruit){
const allFruit = ['apple','banana'];
if(allFruit.includes(fruit)){
console.log(fruit)
}
}
let与const使用
let取代var
let可以完全取代var且没有副作用;
下述例子如果把let替换成var则输出的是undefined,这违反了变量先声明后使用的原则
console.log(a)
let a = 'hello world'
const的使用
let与const之间,const定义的是常量,let定义的是变量;
建议优先使用const,尤其在全局环境中,大多数场景中我们应该在全局优先设置常量然后使用,变量大多数使用在方法体内。
字符串定义
字符串定义应该使用const
推荐eslint规则应限制使用单引号或反引号,且不使用分号,动态字符串应用反引号拼接而不是用加减号。
原因:
- JavaScript编译器会对const进行优化,所以多使用const有利于程序的运行效率;
- 单引号是为了减少不必要的转义;
- 分号,习惯而已个人认为没必要加,精简代码;
- 动态字符串拼接,不用加减号,减少不必要的运算;
// bad
var a = "hello world";
var b = "<div class=\"header\">" + a + "</div>";
// acceptable
const a = 'hello world'
const b = '<div class="header">' + a + '</div>'
// good
const a = 'hello world'
const b = `<div class="header">${a}</div>`
解构赋值
- 减少运算和不必要的语句
深拷贝
单层
// bad
const a = { a: 'a', b: 'b'}
const b = JSON.parse(JSON.stringify(a))
// good
const a = { a: 'a', b: 'b'}
const b = { ...a }
解构赋值
数组赋值
const arr = [ 1, 2, 3, 4]
// bad
const first = arr[ 0 ]
const second = arr[ 1 ]
// good
const [ first, second ] = arr
Array
- 数组拼接使用
unshift
、splice
、push
- Array.sort()数组排序
- Array.filter()过滤
- Array.flat(Infinity)数据扁平化
- Array.Stringify()转字符串
- Array.includes()检测数组包含指定值
- Array.every()全部条件符合
- Array.some()部分条件符合
- Array.find()返回通过函数内判断的第一个元素的值
- Array.findIndex()返回通过函数内判断的第一个元素的下标
- Array.reduce()数组中的每个值作为累加,最终计算为一个值。
Object
- delete obj0.age 删除
- prototype 返回对象类型原型的引用
- Object.keys(obj)对obj中的索引进行循环
- Object.values(obj)对obj中的值进行循环
- Object.entries(obj)循环obj中的某一项
对象的循环调用
let obj = {
name:"张三",
sex:"男",
age:20,
height:150
}
for ( let [key,val] of Object.entries(obj)){
console.log(key,val)
}
// name 张三
// sex 男
// age 20
// height 150
对象尽量静态化
// bad
const obj = {}
obj.newData = 3
// conventional
const obj = {}
Object.assign(obj, { newData:'11' })
// good
const obj = { newData: null }
obj.newData = 3
对象属性名称动态
const varName = () => {
return 'key'
}
// bad
const obj = {
id: 5,
name : 'XiaoMing'
}
obj[varName()] = 123
// good
const obj = {
id: 5,
name : 'XiaoMing',
[varName()]: 123
}
对象属性动态
const obj_B = { a: 'a', b: 'b' }
const obj_C = { c: 'c' }
// bad
const obj_A = {}
obj_A.a = obj_B.a
obj_A.b = obj_B.b
obj_A.c = obj_C.c
// conventional
const obj_A = {
a: obj_B.a,
b: obj_B.b,
c: obj_C.c
}
// good
const obj_A = {
...obj_B,
...obj_C
}
对象属性简写
const obj = {
name: 'name',
// bad
funNameA: function (item) {
console.log('item', item)
},
// good
funNameB: item => console.log('item', item),
// best:
funNameC(item){
console.log('item', item)
}
}
函数
链式调用
返回对象使方法可以链式调用
function Person(name) {
this.name = name
this.sayName = function() {
console.log("Hello my name is: ", this.name)
return this
}
this.changeName = function(name) {
this.name = name
return this
}
}
let person = new Person("John")
person.sayName().changeName("Timmy").sayName()
箭头函数
某些需要使用函数表达式的场合,尽量用箭头函数代替;
省去不必要的return,而且绑定了this,代码更整洁
let arrayA = [1, 2, 3, 4]
let arrayB = []
// bad
arrayA.map(function (x) {
arrayB.push(x * x)
})
// good
arrayB = arrayA.map( x => {
return x * x
})
// best
arrayB = arrayA.map( x => x * x)
函数的参数赋值
// bad
function requestAction( items ) {
const paramA = items.paramA
const paramB = items.paramB
}
// good
function requestAction( items ) {
const { paramA , paramB } = items
}
// best
function requestAction( { paramA , paramB }) {
}
多个函数返回值
// bad
function requestAction() {
return [ valA, valB, val3]
}
// good
function requestAction() {
return { valA, valB, val3 }
}
// best
const { valA, valB, val3 } = requestAction()
函数参数默认值
函数的参数都要设置默认值,这样的的函数才能足够健壮
// bad
function( items ) {
items = items || {}
}
// good
function( items = {} ) {
// ...
}
性能优化
这里的性能优化并不是指是否使用高级函数,是指减少不必要的运算与语句的使用,下面举几个例子
循环优化
在for中定义array.length,每次循环都会重新计算array的长度,所以循环最大限制次数应该是个定值
// bad
for(let i = 0; i < array.length; i++) {
// ...
}
// good
const length = array.length
for(let i = 0; i < length; i++) {
// ...
}
减少运算
加号也算运算
// bad
let testData = '测试数据'
console.log('testData' + testData)
// good
console.log('testData', testData)
最小化语句数
// bad
let a = '1',
let b = '2',
let c = 3
// good
let a = '1',
b = '2',
c = 3
合并语句
// bad
let i = 0
let value = array[i]
i++
// good
let i = 0
let value = array[i++]
写在最后
以上是我针对于前端开发代码优化js部分的一些建议与心得。
希望大家明白,知道高级函数与合理的使用高级函数是两码事。
如何优雅的写出漂亮且高效的代码,严谨的规则、明了的语义和清晰的逻辑思路缺一不可,这样才能结合实际场景合理判断出适用的高阶函数加以使用,万万不可为了使用高级函数而去使用高级函数。
后续更新html+css部分。
分享即学习,欢迎转载,随意抄袭,学到了就是你的。
转载:https://blog.csdn.net/weixin_40009637/article/details/106494227