代码重构技巧(二)

1,977 阅读4分钟

熔断写法

熔断代码说的比较悬,其实就是将条件语句进行简化的一种写法,就和三目是if/else的一种简化一样。我们看下代码的对比效果。

// old codes 
if(isRight){
	fn();
}

// new codes 
isRight && fn();

// better codes 
isRight && fn && fn();

逻辑或--默认值/默认执行

在es6中支持了参数默认值的写法,解决的是某个参数在没有传入的时候取默认值的需求。那么在之前我们是如何解决类似的需求的呢?我们通过逻辑或实现。

// now codes
function getAge(age = 12){
  let ageStr = `${age}岁`
	return ageStr
}
// old codes
function getAge(age ){
  let defaultAge = 12
  let _age = age || defaultAge
  let ageStr = `${_age}岁`
	return ageStr
}

虽然我们已经不需要逻辑或来支持一些参数默认值的实现,但是我们在代码逻辑中类似的需求非常多,尤其一些很简单的逻辑需求如果用过多的条件判断,会让代码变得很臃肿,因此当符合逻辑或需求场景时,我会建议用逻辑或执行。

let age = 12
// old codes
let isAdult = false
// normal codes
if(age && age >= 18){
	isAdult = true
}

// better codes
let isAdult = (age && age >= 18) ? true : false
// better codes
let isAdult = (age && age >= 18) || false


// 无论函数是否传入:默认函数执行的案例 
// 假设我们要实现一段逻辑: 无论是否传参 都执行一个默认函数或者逻辑
function print(fn){
	let defaultFn = ()=>{
  	console.log('默认执行')
  }
	(fn && fn()) || defaultFn()
}


print(()=>{
	console.log('自定义执行')
}) // 执行结果 : 自定义执行 默认执行
print() // 执行结果 : 默认执行


// 如果你期望是传入时 执行传入函数 否则 执行默认函数 那么就和上面的默认参数一个逻辑了 ,
// 不同的是,我们很少将一个函数设为默认函数,而且在维护角度,我们也是期望默认函数维护在函数内部
function print(fn){
	let defaultFn = ()=>{
  	console.log('默认执行')
  }
  let _fn = fn || defaultFn
	return _fn()
}

双层逻辑转换

逻辑值常识

经常有时候我们会写一些逻辑值判断,尤其是针对布尔值的常见判断。而有些冗余的判断是因为我们对一些值转为布尔值时的常识了解远远不够。

比如我经常看到有的同学可能这样写逻辑:

if(classNumber === 0 || classNumber === undefined){
// codes here
}

// 如果你能明确的列出classNumber的所有可能情况,
//其实我们知道 数字0 以及 undefined null 都是属于false的情况
if(!classNumber){
  // codes here 
}

顺带陪大家复习下基本的数据类型转为布尔型数据的值。

image.png

案例

本条的重点不是介绍这些,而是介绍当我们在需要用某些值的判断时可能直接使用存在误差。尤其我在写jsx语法的一些代码时,想使用如果某个值存在那么就使用某个标签或者组件。例如下面这样:

// 作为常识 我们期望 classStatus 存在并且其值为1的时候才可执行 
{ classStatus && classStatus === 1  && <ClassInfo />}
// 但其实际执行结果 在不符合的时候输出却是这样的 
0 
  
// 经过分析我们清楚了这个过程虽然执行到最后会有一个布尔值,但之前的执行结果也一并执行而且返回了
// 于是有人代码就写成了这样,的确解决了问题,因为在代码执行中 前者只作为判断不会作为输出或者返回,
// 但多了没用任何意义的null,除非我们需要额外的在否则的情况下返回其他
  {(classStatus && classStatus === 1)? <ClassInfo />:null}
  
// 所以我一般的建议是 一定要加双层的布尔逻辑,将其每段逻辑转换为布尔值,这样就不会输出额外的标识了 
{!!classStatus && classStatus === 1 && <ClassInfo />}

延伸拓展

其实这样的转换为逻辑值在许多框架的源码中非常常见,因为我们一者不能保证用户一定给的是布尔值,另外也是出于代码更加严谨的角度,我们对传入传入的数值进行一次布尔值转换,比如vue 针对watcher 传入是否深度监听的deep部分,就加了这样的代码。

image.png