• 提高 JavaScript 可读性的 10 个技巧



    每日分享前端插件干货,欢迎关注!

     

    1.日志级别和语义方法

    1. console.log("hello world")
    2. console.warn("this is a warning")
    3. console.error("this is an error")
    4. console.info("this is info")
    5. console.debug("this is debug")
    6. console.trace("show trace")

    如果你尝试console.warn,那么你会得到trace调试信息,这意味着更容易调试代码。

    让我们再试试其他的控制台功能吧:)

    原代码:

    console.log("Error: API key should not be empty")
    

    改进后的代码:

    console.error("Error: API key should not be empty")
    

    2. 避免对布尔变量使用否定意义的名称

    老实说,双重否定理解起来更费劲。

    例如:isStarted vs. isNotStarted

    原代码:

    1. const isInvalidApiKey = apiKey === null
    2. if (isInvalidApiKey) {}

    改进后的代码:

    1. const isValidApiKey = apiKey != null
    2. if (!isValidApiKey) {}

    3. 避免使用标记位参数

    不知道函数使用的标记参数是什么?那么你最好先阅读函数声明。

    原代码:

    1. renderResult(true)
    2. function renderResult(isAuthenticated) {
    3.     if (isAuthenticated) {
    4.        return <p>App</p>
    5.     } else {
    6.         return <p>Please login</p>
    7.     }
    8. }

    使用对象参数:

    1. renderResult({isAuthenticatedtrue})
    2. function renderResult({isAuthenticated}) {
    3.     if (isAuthenticated) {
    4.         return <p>App</p>
    5.     } else {
    6.         return <p>Please login</p>
    7.     }
    8. }

    使用2个函数:

    1. function renderAuthenticatedApp() {
    2.     return <p>App</p>
    3. }
    4. function renderUnAuthenticatedApp() {
    5.     return <p>Please login</p>
    6. }
    7. isAuthenticated ? renderAuthenticatedApp() : renderUnAuthenticatedApp()

    4. 使用卫语句

    首先说一下“卫语句”是什么东西?

    卫语句就是把复杂的条件表达式拆分成多个条件表达式,比如一个很复杂的表达式,嵌套了好几层的if-else语句,将其转换为多个if语句,实现它的逻辑,这多条的if语句就是卫语句。

    例如,原代码即将形成了一个嵌套地狱:

    1. if (statusCode === 200) {
    2.     // success
    3. else {
    4.     if (statusCode === 500) {
    5.         // Internal Server Error
    6.     } else if (statusCode === 400) {
    7.         // Not Found
    8.     } else {
    9.         // Other error
    10.     }
    11. }

    使用卫语句改进后:

    1. if (statusCode === 500) {
    2.     // Internal Server Error
    3. }
    4. if (statusCode === 400) {
    5.     // Not Found
    6. }
    7. if (statusCode !== 200) {
    8.     // Other error
    9. }
    10. // success

    5. 让代码一目了然

    🐨简单易懂

    🐨可重复使用

    🐨长的描述性变量名称胜过冗长的注释

    例如:

    1. // verify that user has added a credit card
    2. function verify(user) {}

    改进后

    function verifyThatUserHasAddedCreditCard(user) {}
    

    再看一个例子:

    1. if (country !== 'finland' &&
    2.     country !== 'germany' &&
    3.     country !== 'vietnam' &&
    4.     country !== 'russia' &&
    5.     type !== '💣'
    6. ) {
    7.     return Promise.reject('Not available')
    8. }

    改进后

    1. const isInAvailableCountries = (
    2.     country === 'finland' ||
    3.     country === 'germany' ||
    4.     country === 'vietnam' ||
    5.     country === 'russia'
    6. )
    7. const hasBoom = type === '💣'
    8. if (!isInAvailableCountries || hasBoom) {
    9.     return Promise.reject('Not available')
    10. }

    创建更合适的条件判断

    1. const availableCountries = ['finland''germany''vietnam''russia']
    2. const isInAvailableCountries = availableCountries.includes(country)
    3. const hasBoom = type === '💣'
    4. if (!isInAvailableCountries || hasBoom) {
    5.     return Promise.reject('Not available')
    6. }

    6. 不可能的状态就让它不可能

    🐨易于理解

    🐨预防出现大量bug

    🐨停止使用类似于isLoading的布尔值

    例如:

    1. isLoadingtrue
    2. isErrorfalse
    3. isLoadingfalse
    4. isErrortrue
    5. // imposible states
    6. isLoadingtrue
    7. isErrortrue

    改进后:

    1. const LOADING_STATE = 'LOADING_STATE'
    2. const ERROR_STATE = 'ERROR_STATE'
    3. const state = LOADING_STATE

    再看一个例子:

    1. const [isLoading, setIsLoading] = React.useState(false)
    2. const [error, setError] = React.useState(null)
    3. const [coffee, setCoffee] = React.useState(null)
    4. function handleButtonClick() {
    5.     setIsLoading(true)
    6.     setError(null)
    7.     setCoffee(null)
    8.     getCoffee('cappuccino''small''finland'true).then(coffee => {
    9.         setIsLoading(false)
    10.         setError(null)
    11.         setCoffee(coffee)
    12.     }).catch(error => {
    13.         setIsLoading(false)
    14.         setError(error)
    15.     })
    16. }

    改进后:

    1. const state = {
    2.     idle'idle',
    3.     loading'loading',
    4.     error'error',
    5.     success'success',
    6. }
    7. const [error, setError] = React.useState(null)
    8. const [coffee, setCoffee] = React.useState(null)
    9. const [status, setStatus] = React.useState(state.idle
    10. function handleButtonClick() {
    11.     setStatus(state.loading)
    12.     getCoffee('cappuccino''small''finland'true).then(coffee => {
    13.         setStatus(state.success)
    14.         setCoffee(coffee)
    15.     }).catch(error => {
    16.         setStatus(state.error)
    17.         setError(error)
    18.     })
    19. }

    7.参数个数太多,可以用对象代替

    🐨参数顺序无关紧要

    🐨方便传递可选参数

    例如:

    1. function getBox(type, size, price, color) {}
    2. getBox('carry'undefined10'red')

    改进后:

    1. function getBox(options) {
    2.     const {type, size, price, color} = options
    3. }
    4. getBox({
    5.     type'carry',
    6.     price: 10,
    7.     color: 'red'
    8. })

    8. 使用Object.assign赋默认值

    例如:

    1. function getBox(options) {
    2.     options.type = options.type || 'carry'
    3.     options.size = options.size || 'small'
    4.     options.price = options.price || 10
    5.     options.color = options.color || 'red'
    6.     const {type, size, price, color} = options
    7. }

    改进后:

    1. function getBox(customOptions) {
    2.     const defaults = {
    3.         type'carry',
    4.         size'small',
    5.         price10,
    6.         color'red',
    7.     }
    8.     const options = Object.assign(defaults, customOptions)
    9.     const {type, size, price, color} = options
    10. }

    原代码:

    1. export function getCoffee(type, size, country, hasIce) {
    2.     type = type || 'cappuccino'
    3.     size = size || 'small'
    4.     country = country || 'finland'
    5.     hasIce = hasIce || false
    6. }

    可以用以下3个方法改进:

    1. function getCoffee(customOptions) {
    2.     const defaultOptions = {
    3.         type'cappuccino',
    4.         size'small',
    5.         country'finland',
    6.         hasIcefalse
    7.     }
    8.     const options = Object.assign(defaultOptions, customOptions)
    9. }
    10. function getCoffee(options = {}) {
    11.     const {
    12.         type = 'cappuccino',
    13.         size = 'small',
    14.         country = 'finland',
    15.         hasIce = false
    16.     } = options
    17. }
    18. function getCoffee({
    19.     type = 'cappuccino'
    20.     size = 'small',
    21.     country = 'finland',
    22.     hasIce = false
    23. } = {}) {
    24. }

    9. 用对象字面量替换switch语句

    老实说,我也喜欢switch,但我其实并不知道什么时候使用switch语句和对象字面量。我依靠直觉来判断该选哪一个。

    例如:

    1. let drink
    2. switch(type) {
    3.     case 'cappuccino':
    4.         drink = 'Cappuccino';
    5.         break;
    6.     case 'flatWhite':
    7.         drink = 'Flat White';
    8.         break;
    9.     case 'espresso':
    10.         drink = 'Espresso';
    11.         break;
    12.     default:
    13.         drink = 'Unknown drink';
    14. }

    可以改进为:

    1. const menu = {
    2.     'cappuccino': 'Cappuccino',
    3.     'flatWhite': 'Flat White',
    4.     'espresso': 'Espresso',
    5.     'default': 'Unknown drink'
    6. }
    7. const drink = menu[type] || menu['default']

    避免不合理的抽象

    我不知道如何创建好的抽象,但我知道我创建了很多坏的抽象。

    凡是皆有两面性。为了减少代码重复,我们牺牲了改变需求的能力。这不是一笔好的交易。——Dan Abramov

    下面的代码用于获取订单,且我使用了Redux进行状态管理。这就是样板!!!如果我们在匆忙之下创建了这样的抽象:

    获取订单

    1. // Action Type
    2. const FETCH_ORDERS_START = "FETCH_ORDERS_START";
    3. const FETCH_ORDERS_SUCCESS = "FETCH_ORDERS_SUCCESS";
    4. const FETCH_ORDERS_FAILED = "FETCH_ORDERS_FAILED"
    1. // Action
    2. export const fetchOrder = (token) => {
    3.     return dispatch => {
    4.         dispatch(fetchOrdersStart);
    5.         axios.get('/orders.json?auth=' + token).then(res => {
    6.             dispatch(fetchOrdersSuccess(res));
    7.         }).catch(err => {
    8.             dispatch(fetchOrdersFailed(err));
    9.         });
    10.     };
    11. }
    12. export const fetchOrdersSuccess = (orders) => {
    13.     return {
    14.         type: FETCH_ORDERS_SUCCESS,
    15.         orders: orders,
    16.     };
    17. };
    18. export const fetchOrdersFailed = (error) => {
    19.     return {
    20.         type: FETCH_ORDERS_FAILED,
    21.         error: error,
    22.     };
    23. };
    24. export const fetchOrdersStart = () => {
    25.     return {
    26.         type: FETCH_ORDERS_START,
    27.     };
    28. };

    我敢打赌你必须得阅读完所有的代码才能理解该抽象。所以应该这样改进:

    1. // Action
    2. const moduleName = 'order'
    3. const path = '/order'
    4. const {moduleActionTypes, moduleActions} = useModuleActions(moduleName, path)
    5. function fetchOrder() {
    6.     moduleActionTypes.getModel()    
    7. }
    8. function updateOrder(data) {
    9.     moduleActionTypes.updateModel(data)
    10. }

    感谢阅读!如果你觉得文章写的对你有帮助的话,也欢迎分享给你的朋友!

     

     

    每日分享前端插件干货,欢迎关注!

  • 相关阅读:
    podman创建helloWord镜像实例-参考docker
    JAVA 之 Spring框架学习 1:Springの初体验 IOC DI
    Spring Cloud Feign实战
    #案例:web自动化的一个案例!字节跳动!写到csv文件中!
    深度学习入门篇(一):环境搭建(PyTorch+Anaconda3+CUDA+PyCharm )
    PyCharm连接远程Docker环境
    春节静态HTML网页作业模板 传统节日文化网站设计作品 静态学生网页设计作业简单网页制作
    813. 最大平均值和的分组-动态规划算法
    “/etc/apt/sources.list.d“和文件/etc/apt/sources.list的不同
    Zookeeper特性与节点数据类型详解
  • 原文地址:https://blog.csdn.net/weixin_43044226/article/details/125582969