最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 通俗易懂的 JavaScript 代码优化实践

    正文概述 掘金(ihoneys)   2021-08-16   629

    这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

    前言

    在这篇短文中,将会介绍一些在开发过程中一些实用的方法来改进你的代码,简单易懂,通俗实用。

    指定默认值

    在读取属性的时候我们希望,属性值在 null 或者 undefined 的时候能够指定默认值,避免执行引用出现bug,我们可以使用 || 运算符

    // 比如后端数据返回的message为null,就使用我们自动定义的text
    const { message } = response.data;
    const myMessage = message || '返回数据失败'
    

    注意的是,如果 message的值为 ''或者 false0 默认值同样会生效。但是如果是 {},或者 [],则不会取默认值!

    函数默认参数替代短路运算符

    const useName = (name) => {
      const myName = name || "Jason";
      // ...
    }
    
    const useName = (name = "Jason") => {
      // ...
    }
    

    && 代替单个 if

    例如与后台数据交互,拿到返回数据需要遍历进行操作。

    // 为了避免数据为数组能够遍历
    if(Array.isArray(data)) {
        data.forEach(item => {})
    }
    
    // 使用 && 运算符 当请求接口返回数据需要循环处理数据的时候可以:
    Array.isArray(data) && data.forEach(item => {})
    
    

    三目运算符号

    三目运算符能够简化我们的 if else 条件判断,适当我们可以用它来代码,简化我们的代码

    let key = value === 0 ? "buy" : "sell"
    

    或者还有第三种情况的时候我们可以嵌套

    let key = ""
    if(value === 0) {
        str = "buy"
    } else if (value === 1) {
        str = "/"
    }  else {
        str = "sell"
    }
    
    // 嵌套三目
    let str =  value === 0 ? "buy" : value === 1 ? "/" : "sell"
    

    链式判断运算符号 ?.

    往往我们需要获取一个深层对象属性值时,需要进行多次判断,如果不判断,有一个没有就会报错,导致后面代码无法运行下去,就会提示:

    Cannot read property 'xxx' of undefined

    const $name = app.config.globalProperties.$name // error
    
    const $name =
          (app &&
           app.config &&
           app.config.globalProperties &&
           app.config.globalProperties.$name) ||
          "Jason";
    
    // 使用 ?. 运算符
    const $name = app?.config?.globalProperties?.$name  
    

    解构赋值

    数据解构赋值

    多个变量赋值的时候,我们可以使用数据解构赋值

    let name = "Jason";
    let age = "18";
    let sex = "男";
    
    // 数组解构赋值
    let [name, age, sex] = ["Jason", "18", "男"];
    

    对象解构取值

    const userInfo = {
        name: "Jason",
        age: "18",
        sex: "男",
    };
    const { name, age, sex } = userInfo;
    
    // 顺便说一下 es6 对象中键值同名可以简写
    const name = "Jason"
    const userInfo = {
        name,
        ...
    };
    

    ... 扩展运算符

    扩展运算符也可以相当于 concat() 连接两个数组,比如移动端一个商品列表需要分页加载

    使用模板字符

    ES6模板字符串让我们连接字符串的时候不用更加繁琐

    // 比如获取时间拼接
    function getYearsMonthDay() {
        function addDateZero(num) {
            return num < 10 ? "0" + num : num;
        }
        const d = new Date();
        const [years, month, day] = [d.getFullYear(), d.getMonth(), d.getDate()];
       
        return return years + "年" + addDateZero(month + 1) + "月" + addDateZero(day) + "日"
    }
    
    // 模板字符串
    function getYearsMonthDay() {
        // ...
        return `${years}年${addDateZero(month + 1)}月${addDateZero(day)}日`;
    }
    

    使用 let、const 代替 var

    避免了内层可能会覆盖外层变量,减少bug的源头,let、const的规范使用也能够提升代码编译的效率。

    var name = "Jason"
    
    // better
    const name = "Jason"
    
    // 如果不是一个常量就用 let
    let name = "Jason"
    

    箭头函数

    箭头函数表达式的语法比函数表达式更简洁。

    // 这里使用 vue3 computed
    // function
    const statusArr = [2, 4, 5, 6, 8, 9];
    const showBtn = computed(() => {
        return function (status) {
            return statusArr.includes(status);
        };
    });
    
    // 使用箭头函数
    const computedShowBottomBtn = computed(
        () => (status) => statusArr.includes(status)
    );
    

    ps:哈哈 不过使用箭头函数,打包还得 babel 转换,量越大需要转换就越多,所以?~

    return 减少缩进

    if(!isObjEmpty(data)) {
        // do something
    }
    
    if(isObjEmpty(data)) return
    // ...
    

    简化判断

    条件提取

    一个 if 条件需要多足多种情况时,我们可以将条件提取出来,代码更加清晰。

    if ((name === "Jason" || sex === 20) && (name === "Alisa" || sex === 18)) {
        // ...
    }
    
    // 改进
    const condition1 = () => {
        return name === "Jason" || sex === 20;
    };
    
    const condition2 = () => {
        return name === "Alisa" || sex === 18
    }
    
    if (condition1() && condition2()) {
        // ...
    }
    

    includes 简化

    includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

    比如判断某一个值符合是否其中一个条件

    // 通常使用 || 
    if (status === 2 || status === 3 || status === 4 || status === 5) {
        // do something
    }
    
    // includes 简化
    const passStatus = [2, 3, 4, 5]
    if (passStatus.includes(status)) {
        // do something
    }
    
    

    switch

    多条件判断,可以使用普通 switch 判断:

    比如根据返回请求状态自定义状态码的 message

    switch(error.response.status) {
        case 302: message = '接口重定向了!';break;
        case 400: message = '参数不正确!';break;
        case 401: message = '您未登录,或者登录已经超时,请先登录!';break;
        case 403: message = '您没有权限操作!'; break;
        case 404: message = `请求地址出错: ${error.response.config.url}`; break;
        case 408: message = '请求超时!'; break;
        case 409: message = '系统已存在相同数据!'; break;
        case 500: message = '服务器内部错误!'; break;
        case 501: message = '服务未实现!'; break;
        case 502: message = '网关错误!'; break;
        case 503: message = '服务不可用!'; break;
        case 504: message = '服务暂时无法访问,请稍后再试!'; break;
        case 505: message = 'HTTP版本不受支持!'; break;
        default: message = '请求异常'; break
    }
    

    抽象配置

    或者通过抽象配置键值的方式将逻辑判断进行简化更简单。

    const mapMessage = {
        302: "接口重定向了!",
        400: "参数不正确!",
        401: "您未登录,或者登录已经超时,请先登录!",
        403: "您没有权限操作!",
        404: `请求地址出错: ${error.response.config.url}`,
        408: "请求超时!",
        409: "系统已存在相同数据!",
        500: "服务器内部错误!",
        501: "服务未实现!",
        502: "网关错误!",
        503: "服务不可用!",
        504: "服务暂时无法访问,请稍后再试!",
        505: "HTTP版本不受支持!",
    };
    
    const message = mapMessage[error.response.status] || "请求异常"
    

    这种写法的好处在于,将判断条件作为属性名,将处理逻辑做为对象的属性值。

    使用 map

    const action = new Map([
        [302, "接口重定向了!"],
        [400, "参数不正确!"],
        ...
    ]);
    
    // 匹配
    const message = action.get(error.response.status);
    

    表单判断优化

    有一些需求有多个表单,一般我们的 UI 框架(比如 Vant、Ant-d)是在 input 组件下方有警告提示,但是一些列如上传,还有 swtich 没有对应提示,需要我们弹窗提示它未填未选等等。

    不好的写法:

    if (!CardPositiveImage) {
       createMessage('未上传证件正面!');
       return false;
    }
    if (!name) {
        createMessage('未填写姓名!');
        return false;
    }
    if (!checkPhone(phone)) {
        createMessage('手机号码不正确!');
        return false;
    }
    // ...
    

    好的写法:

    const validateForm = () => {
        const rules = [
            {
                value: CardPositiveImage,
                text: "未上传证件正面!",
            },
            {
                value: checkPhone(state.patientPhone),
                text: "手机号码不正确!",
            },
            {
                value: name,
                text: "未填写姓名!",
            },
        ];
        
        // 也可以把validateFunc这一块抽离出来 可能多出有表单
        const validateFunc = (arr) => {
            const action = arr.filter(item => !item.value);
            if (action.length) {
                createMessage(action[0].text);
                return false
            }
            return true
        }
        return validateFunc(rules);
    };
    
    // 表单提交
    const onSubmitForm = () => {
        if (!validateForm()) return // 执行验证
        
        // ...
    }
    

    函数参数过多,利用 Object 传递,并使用解构

    ?
    const getUserInfo = (name, sex, height, age) => {
        // ...
    };
    getUserInfo("Jason", "男", "176", "18");
    
    ?
    const getUserInfo = ({ name, age, sex, height }) => {
        // ...
    };
    getUserInfo({
        name: "Jason",
        age: "18",
        sex: "男",
        height: "176",
    });
    

    单一职责,提炼函数

    简单说一个例子比如一个函数中负责表单提交

    ?
    const handleNext = () => {
        // 验证表单
    	const rules = [
            {
                value: CardPositiveImage,
                text: "未上传证件正面!",
            },
            {
                value: checkPhone(state.patientPhone),
                text: "手机号码不正确!",
            },
            {
                value: name,
                text: "未填写姓名!",
            },
        ];
        const action = rules.filter(item => !item.value);
        if (action.length) {
            createMessage(action[0].text);
            return false
        }
        
       // 拿到需要传递给后端的数据
       const baseData = {
           name: state.name,
           age: state.age
           ...
       }
       const moreData = {
           phone: state.phone
           ...
       }
       
       const complete = curIndex ? Object.assign(baseData, moreData) : baseData
    }
    
    
    ?
    const validateForm = () => {
        const rules = [
            {
                value: CardPositiveImage,
                text: "未上传证件正面!",
            },
            ...
        ];
        // 也可以把validateFunc这一块抽离出来 可能多出有表单
        const validateFunc = (arr) => {
            const action = arr.filter(item => !item.value);
            if (action.length) {
                createMessage(action[0].text);
                return false
            }
            return true
        }
        return validateFunc(rules);
    };
    
    const postData = () => {
        const baseData = {
            name: state.name,
            age: state.age
            ...
        }
        const moreData = {
            phone: state.phone
            ...
        }
    
        return curIndex ? Object.assign(baseData, moreData) : baseData
    }
    
    const handleNext = () => { 
        // 验证表单
        if (!validateForm()) return 
        // 数据
        const data = postData()
        
        // .. 提交请求
    }
    

    最后

    上面总结一些 基础的 js 一些小操作,当然使用 Vue、React 框架如何优雅编写组件也是一问学问,后面一起探究研究~


    起源地下载网 » 通俗易懂的 JavaScript 代码优化实践

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元