开头
JS是一门弱类型、很灵活的语言,当然现在有了TS,但是在一些项目里面不可避免的还是要使用JS来开发
这次小编Peter老师
就总结了日常的几个让小姐姐们看了直呼“好厉害”
的JS写法(优秀的实践,写出健壮持久的代码
)
防止出现空值
当需要解构赋值的时候,给一个默认值,例如:
const {foo= {} } = props.obj;
return <div>{foo.count && <Count/>}</div>
这样可以避免当props.obj.foo
为空对象时候,出现后面代码运行时错误
当然现在也有可选链
可选链操作符( ?. )
允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回undefined
。
上面的代码也可以这样写,同样不会出现报错:
const {foo= {} } = props.obj;
return <div>{props?.obj?.foo?.count && <Count/>}</div>
具体可看MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Optional_chaining
前端大部分的报错都是来自于出现了运行时的错误,例如undefined.count
这样的代码,就会导致js报错,运行可能会卡住
这一点注意好,能大幅提升项目的健壮性,更加持久!
把项目中用到的字符串、数字等定义为常量
例如你的项目中出现了
![](https://img-blog.csdnimg.cn/img_convert/a6b42b44f9beb955ed1beb61ba99c15d.png)
新的创作
这几个字,但是后面有没有可能改成:新的文章
?
而且新的创作
这四个字,会不会其他很多地方都会用到,哪一天会不会统一改?
如果你定义成一个常量,统一管理,那么下次要修改的时候,你很快就能全局替换(当然你也可以用vscode的全局替换功能)
![](https://img-blog.csdnimg.cn/img_convert/443ed9e5909a86ac725a2913d32ef127.png)
这样就可以全局替换你的内容了,但是建议定义成常量,特别是一些具有特殊意义的id,日期等等。
总结:将来功能必改,此处不要写死 - 鲁迅
![](https://img-blog.csdnimg.cn/img_convert/6981a8ab2167c971fdae05782a4c54a4.png)
不要多重嵌套三目运算符
例如当你写下:
const isShow = count > 0 ? list.length !==0 || !foo && disabled
如何优化:
当遇到复杂的判断逻辑,就像需要很多个if else
的场景一样,需要分析,拆解
把优先级比较高的先定义成变量,如果不符合条件就直接return
,例如这个isShow,就可以定义成一个函数:
function getShow ({count,list,foo,disabled}){
if(count < 0 ){return false}
return ...
}
这样就可以避免出现复杂的三目运算符
函数拆解,单一职责
例如你写了一个函数,需要通过多个接口获取数据的值才能判断这个时候能否做某件事
那么需要拆解成多个单职责的函数,这样方便后期的单元测试,也便于阅读维护代码
async function getDisabled (){
const count =await getCount();
const isAllow = await getAllow();
return count && isAllow;
}
不写无法控制的异步代码
例如:
let count = 1;
...若干js代码
setTimeout(async ()=>{
const res = await getRes();
if(res){
count = 0;
}
},500)
...若干js代码
setTimeout(()=>{
if(count!==0){
//do something
}
},1500)
这样的代码,在Promise普及的年代,应该使用确定的任务调度方式编写异步代码,如果是串行就用Promise.then/async await/generator函数
,如果是并行就用Promise.all
例如串行:
getCount().then((count)=>{
if(count > 0){
//do something
}
})
例如并行:
const [count,list] = await Promise.all(getCount,getList);
Promise.all这里使用的是数组结构赋值
数组快速结构赋值
别再写
const one = arr[0];
这样的代码了
可以:
const arr = [1,2,3];
const [one,two] = [arr];
// one = 1, two =2
用Class
代替操作原型
总是用 Class,取代需要 prototype 的操作。因为 Class 的写法更简洁,更易于理解。
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
使用extends实现继承,因为这样更简单,不会有破坏instanceof运算的危险。
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
return this._queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
这个Class抄的阮一峰老师的,
https://es6.ruanyifeng.com/#docs/style
现在的Nodejs源码里面就有很多操作原型代码,导致我之前阅读的体验很差。
结语
几个简单实用的编码习惯就这样总结给大家,大道至简,最近一年我特别注意这个事,下班后基本没有接到过修BUG的电话。
关注我,关注我的公众号:前端巅峰
,来波????/在看/关注
支持一波!