分享即学习,欢迎转载,随意抄袭,学到了就是你的。
首先说明,本文仅供优化的方向和思路,会举例说明,并不代表所有的语法都要这么写,要结合应用场景与当前开发团队的平均水平,合理使用,而不是一味追求优化而去要求团队的代码风格,如果非要追求代码的统一性,也应该把业务处理或数据处理的方法变成共通方法,让开发人员调用。
在没有足够的时间和经验以及项目积累的情况下,时刻谨记,按时完成任务才是关键,完成任务是主优化代码其次。
提到优化,大多数想到的场景都是性能优化。
以前,由于浏览器以及网速的限制,代码性能优化就显得极为重要。
但在如今,谷歌浏览器独步天下已成必然,网速更是直线飞起,互联网产品的版本更新迭代更加频繁。
所以,应该适度考虑牺牲一点点性能,而去做代码层次的优化。
语义清晰、逻辑明了的代码既可以增强开发效率,同时也更利于增强代码的可读性、降低维护成本、版本迭代更新。
恰到好处的高级函数使用才是对于前端代码优化的最好方向,而不是一味地追求性能。
言归正传,优化的思路主要考虑以下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在每次循环时都执行。
所以,不论是考虑代码的性能还是、可读性,合理的使用高级函数才对代码的最好优化。
以判断语句为例,优化之时应考虑以下几点:
// 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可以完全取代var且没有副作用;
下述例子如果把let替换成var则输出的是undefined,这违反了变量先声明后使用的原则
console.log(a)
let a = 'hello world'
let与const之间,const定义的是常量,let定义的是变量;
建议优先使用const,尤其在全局环境中,大多数场景中我们应该在全局优先设置常量然后使用,变量大多数使用在方法体内。
字符串定义应该使用const
推荐eslint规则应限制使用单引号或反引号,且不使用分号,动态字符串应用反引号拼接而不是用加减号。
原因:
// bad
var a = "hello world";
var b = "" + a + "";
// acceptable
const a = 'hello world'
const b = '' + a + ''
// good
const a = 'hello world'
const b = `${
a}`
单层
// 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
unshift
、splice
、push
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部分。
分享即学习,欢迎转载,随意抄袭,学到了就是你的。