看完这篇,让您的js优雅一个档次

在这里插入图片描述

上图是我阅读书籍——代码整洁之道,绘制的思维导图。写本篇博客的目的是为了加强记忆,其中关于类模块没有总结,是因为最近在研究设计模式,有一定基础后,写一篇设计模式的学习笔记,其中会包括关于写类需要注意的整洁。

一,命名

采用描述性名称

bad

//获取当前时间
let yyddss = new Date();

good

let curDate = new Date();
说明副作用

bad

function getOss(){
    if(!oss){
        return new Oss();
    }
    return oss;
}

good

function createOrReturnOss(){
    if(!oss){
        return new Oss();
    }
    return oss;
}

oss不存在则创建,否则返回oss。名称createOrReturnOss恰当表述清楚。

避免编码

bad

class Person{
    p_name = '整洁';
	p_age = '20';
	//...
}

good

class Person{
 	name = '整洁';
	age = '20';
	//...
}

m_,f_之类的前缀没有意义

统一的命名规则
构造函数使用大驼峰命名

bad

function user(){
    //...
}
let u = new user();

good

function User(){
    //...
}
let user = new User();
变量,函数使用小驼峰或下划线分隔

bad

let myname = '整洁';
function getname(){
    //...
}

good

let my_name = '整洁';
//或
let myName = '整洁';
function getName(){
    //...
}
//或
function get_name(){
    //...
}
清除魔法字符,数字

不要有硬代码,字符串,数字使用变量进行命名

bad

setTimeout(()=>{
    //...
},200);

good

const  WAIT_TIME = 200;
setTimeout(()=>{
    //...
}, WAIT_TIME)

二,注释

不在代码中保存注释掉的代码

有git版本控制,不需要担心代码丢失,需要时查看历史记录找回即可

bad

getName();
//getAge();
//getWifeName();

good

getName();
减少注释

好的代码就是文档,需要写注释前优先考虑重构代码。将精力花写出整洁有表达力的代码,而不是写大量的注释

bad

//data是否含有id
function isIdIncludeData(data,id){
    //数组长度
    let len = data.length;
    //循环数组
    for(let i = 0;i<len;i++){
        //如果存在则返回true
        if(id === data[i]){
            return true;
        }
    }
    //不存在则返回false
    return false;
}

good

//data是否含有id
function isIdIncludeData(data,id){
    let len = data.length;
    for(let i = 0;i<len;i++){
        if(id === data[i]){
            return true;
        }
    }
    return false;
}

三,函数

参数越少越好

参数增多,参数组合传入就越多,不利用于测试,而且参数越多说明该函数做的不只一件事情。不可避免时可以使用一个对象包裹传入

bad

function createPerson (name,age,sex){
   //...
}

good

let personInfo = {
    name:'js',
    age:20,
    sex:'men'
}
function createPerson (personInfo){
    //...
}
一个函数只做一件事

bad

function isAdmin(admin){
    let isInAdmins = admins.includes(admin);
    if(isAdmin){
        arrs.forEach(arr=>{
            //...
        })
        return true;
    }
    datas.forEach(data=>{
        //...
    })
    return false;
}

good

function arrsEach(){
    arrs.forEach(arr=>{
        //...
    })
}
function datasEach(){
    datas.forEach(data=>{
        //...
    })
}
function isAdmin(admin){
    return admins.includes(admin);
}
function arrsOrDatasEach(){
    isAdmin()? arrsEach():datasEach();
}
删除死函数

删除代码中不调用的函数,需要时历史记录中找回

bad

function getName(){
    //...
}
function getAge(){
    //...
}
getName();

good

function getName(){
    //...
}
getName();
分离try...catch...

try...catch...中的代码使用函数包裹,分离出来。

bad

function haveError(){
    try{
        datas.forEach(data=>{
            //....
        })
    }catch(e){
        //...
    }
}

good

function haveError(){
    try{
       datasEach(); 
    }catch(e){
        //...
    }
}
function datasEach(){
    datas.forEach(data=>{
        //....
     })
}
不重复
类似功能抽离公共代码

bad

function arrsEach(){
    arrs.forEach(arr=>{
        //...
    })
}
function datasEach(){
    datas.forEach(data=>{
        //...
    })
}
function isAdmin(admin){
    return admins.includes(admin);
}
function arrsOrDatasEach(){
    isAdmin()? arrsEach():datasEach();
}

good

function each(params){
    params.forEach(param=>{
    	//...           
    })
}
function isAdmin(admin){
    return admins.includes(admin);
}
function arrsOrDatasEach(){
    isAdmin()? each(arrs):each(datas);
}
减少if...else...switch...case...嵌套链

bad

function getType(data){
    let type = typeof data,
     stringType = 'string',
     numberType = 'number',
     //...;
    if(type === stringType){
      	Number(data);
    }else if(type===numberType){
        String(data);
    }
    //...
}

good

let typeMaps = new Map([
    ['string',data=>{
        Number(data);
    }],
    ['number',data=>{
        String(data);
    }]]);
function getType(data){
    let type = typeof data;
    typeMaps.has(type)&&typeMaps.get(type)();
}
判断条件
封装判断条件

bad

if(isHavePerson()&&isAdmin()){
   //...
}

good

if(isPoss()){
   //...
 }
避免否定性条件

bad

function isHavePerson(){
    //...
}
if(!isHavePerson()){
   //...
 }

good

function isHavePerson(){
    //...
}
if(isHavePerson()){
   //...
 }
封闭边界条件

bad

if(num+1>2){
 //...  
 }

good

let one = 1,
    two = 2,
    sum = num + one,
    isBigger = sum > two;
if(isBiggeer){
    //...
}

四,对象和数据结构

使用getters,setters

javaScipt没有接口或类型,也没有publicprivate关键字。

使用原因:

  • 获取一个对象属性在背后做更多的事情,不需要在代码库中查找修改每一处访问;
  • set方便添加已验证;
  • 封装内部实现;
  • 使用getting,setter时,容易添加日志和错误处理
  • 延迟加载对象属性,从服务器获取值然后在赋值给对象属性

bad

class Person{
    constructor(age = 20){
        this.age = age;
    }
}
const person = new Person ();
person.age = 120;
console.log(person.age);

good

class Person {
    constructor(age = 20){
        this._age = age;
    }
    set age(val){
        //年龄大于100或小0,为不合理
        let isErrorAge = val>100||val<0;
        isErrorAge ? null:this._age = val;
    }
    
    get age(){
        return this._age;
    }
}
const person  = new Person ();
person.age = 120;
console.log(person.age);
私有成员

利用ES5闭包实现

bad

function Person(name){
    this.name = name;
}
Person.prototype.getName = function (){
    return this.name;
}
const person  = new Person ('hai');
person.getName();//hai
delete person.name;
person.getName();//undefind

good

function Person(name){
   this.getName = function (){
       return name;
   }
}
const person  = new Person ('hai');
person.getName();//hai
delete person.name;
person.getName();//hai
//或es6 class
class Person {
    //私有成员 ES2020新添加语法,#前缀声明私有成员
    #age;
    constructor(age = 20) {
        this.#age = age;
    }
	setAge(age){
        this.#age = age;
    }
    getAge() {
        return this.#age;
    }
}
参考jquery链式调用思想

jquery中讲究链式调用,链式调用使用代码更加简洁,减少逻辑。每个方法最后均返回this

bad

class Person {
	constructor(){
		this.name = 'hai';
		this.age = 20;
		this.sex = 'man';
	}
	setName(name){
		this.name = name;
	}
	setAge(age){
		this.age = age;
	}
	setSex (sex){
		this.sex = sex;
	}
}
const person =new  Person();
person.setName('java');
person.setAge(25);
person.setSex('wemen');

good

class Person{
   constructor(){
		this.name = 'hai';
		this.age = 20;
		this.sex = 'man';
	}
	setName(name){
		this.name = name;
        return this;
	}
	setAge(age){
		this.age = age;
        return this;
	}
	setSex (sex){
		this.sex = sex;
        return this;
	}
}
const person = new Person();
person.setName('java')
	  .setAge(25)
	 .setSex('wemen');

五,代码美化

注意代码格式,当然我们要借助工具,自动格式化代码。

函数调用方与被调用方应该靠近

人习惯性地从上往下进行阅读。由于这个原因,代码应该按从上往下让人阅读

bad

class Person {
    name = 'javaScipt';
    age = 20;
    wife = "java";
    setAge(age) {
        this.age = age;
    }
    getAge() {
        return this.age;
    }
    getWife() {
        return this.wife;
    }
    setWife(name) {
        this.wife = name;
    }
    getSelfInfo() {
        return `名字:${this.getName()},年龄:${this.getAge()},女朋友:${this.getWife()}`
    }
    setName(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}
const person = new Person();
console.log(person.getSelfInfo());

good

class Person {
    name = 'javaScipt';
    age = 20;
    wife = "java";
    setName(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
    setAge(age) {
        this.age = age;
    }
    getAge() {
        return this.age;
    }
    setWife(name) {
        this.wife = name;
    }
    getWife() {
        return this.wife;
    }
    getSelfInfo() {
        return `名字:${this.getName()},年龄:${this.getAge()},女朋友:${this.getWife()}`
    }
}
const person = new Person();
console.log(person.getSelfInfo());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值