- console.log("hello world")
- console.warn("this is a warning")
- console.error("this is an error")
- console.info("this is info")
- console.debug("this is debug")
- 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")
老实说,双重否定理解起来更费劲。
例如:isStarted
vs. isNotStarted
原代码:
- const isInvalidApiKey = apiKey === null
-
- if (isInvalidApiKey) {}
改进后的代码:
- const isValidApiKey = apiKey != null
-
- if (!isValidApiKey) {}
不知道函数使用的标记参数是什么?那么你最好先阅读函数声明。
原代码:
- renderResult(true)
-
- function renderResult(isAuthenticated) {
- if (isAuthenticated) {
- return <p>App</p>
- } else {
- return <p>Please login</p>
- }
-
- }
使用对象参数:
- renderResult({isAuthenticated: true})
-
- function renderResult({isAuthenticated}) {
- if (isAuthenticated) {
- return <p>App</p>
- } else {
- return <p>Please login</p>
- }
-
- }
使用2个函数:
- function renderAuthenticatedApp() {
- return <p>App</p>
- }
-
- function renderUnAuthenticatedApp() {
- return <p>Please login</p>
- }
-
- isAuthenticated ? renderAuthenticatedApp() : renderUnAuthenticatedApp()
首先说一下“卫语句”是什么东西?
卫语句就是把复杂的条件表达式拆分成多个条件表达式,比如一个很复杂的表达式,嵌套了好几层的
if-else
语句,将其转换为多个if
语句,实现它的逻辑,这多条的if
语句就是卫语句。
例如,原代码即将形成了一个嵌套地狱:
- if (statusCode === 200) {
- // success
- } else {
- if (statusCode === 500) {
- // Internal Server Error
- } else if (statusCode === 400) {
- // Not Found
- } else {
- // Other error
- }
- }
使用卫语句改进后:
- if (statusCode === 500) {
- // Internal Server Error
- }
-
- if (statusCode === 400) {
- // Not Found
- }
-
- if (statusCode !== 200) {
- // Other error
- }
-
- // success
🐨简单易懂
🐨可重复使用
🐨长的描述性变量名称胜过冗长的注释
例如:
- // verify that user has added a credit card
- function verify(user) {}
改进后
function verifyThatUserHasAddedCreditCard(user) {}
再看一个例子:
- if (country !== 'finland' &&
- country !== 'germany' &&
- country !== 'vietnam' &&
- country !== 'russia' &&
- type !== '💣'
- ) {
- return Promise.reject('Not available')
- }
改进后
- const isInAvailableCountries = (
- country === 'finland' ||
- country === 'germany' ||
- country === 'vietnam' ||
- country === 'russia'
- )
-
- const hasBoom = type === '💣'
-
- if (!isInAvailableCountries || hasBoom) {
- return Promise.reject('Not available')
- }
创建更合适的条件判断
- const availableCountries = ['finland', 'germany', 'vietnam', 'russia']
- const isInAvailableCountries = availableCountries.includes(country)
-
- const hasBoom = type === '💣'
-
- if (!isInAvailableCountries || hasBoom) {
- return Promise.reject('Not available')
- }
🐨易于理解
🐨预防出现大量bug
🐨停止使用类似于isLoading
的布尔值
例如:
- isLoading: true
- isError: false
-
- isLoading: false
- isError: true
-
- // imposible states
- isLoading: true
- isError: true
改进后:
- const LOADING_STATE = 'LOADING_STATE'
- const ERROR_STATE = 'ERROR_STATE'
-
- const state = LOADING_STATE
再看一个例子:
- const [isLoading, setIsLoading] = React.useState(false)
- const [error, setError] = React.useState(null)
- const [coffee, setCoffee] = React.useState(null)
-
- function handleButtonClick() {
- setIsLoading(true)
- setError(null)
- setCoffee(null)
-
- getCoffee('cappuccino', 'small', 'finland', true).then(coffee => {
- setIsLoading(false)
- setError(null)
- setCoffee(coffee)
- }).catch(error => {
- setIsLoading(false)
- setError(error)
- })
- }
改进后:
- const state = {
- idle: 'idle',
- loading: 'loading',
- error: 'error',
- success: 'success',
- }
-
- const [error, setError] = React.useState(null)
- const [coffee, setCoffee] = React.useState(null)
- const [status, setStatus] = React.useState(state.idle)
-
- function handleButtonClick() {
- setStatus(state.loading)
-
- getCoffee('cappuccino', 'small', 'finland', true).then(coffee => {
- setStatus(state.success)
- setCoffee(coffee)
- }).catch(error => {
- setStatus(state.error)
- setError(error)
- })
- }
🐨参数顺序无关紧要
🐨方便传递可选参数
例如:
- function getBox(type, size, price, color) {}
-
- getBox('carry', undefined, 10, 'red')
改进后:
- function getBox(options) {
- const {type, size, price, color} = options
- }
-
- getBox({
- type: 'carry',
- price: 10,
- color: 'red'
- })
例如:
- function getBox(options) {
-
- options.type = options.type || 'carry'
- options.size = options.size || 'small'
- options.price = options.price || 10
- options.color = options.color || 'red'
-
- const {type, size, price, color} = options
- }
改进后:
- function getBox(customOptions) {
-
- const defaults = {
- type: 'carry',
- size: 'small',
- price: 10,
- color: 'red',
- }
-
- const options = Object.assign(defaults, customOptions)
-
- const {type, size, price, color} = options
- }
原代码:
- export function getCoffee(type, size, country, hasIce) {
-
- type = type || 'cappuccino'
- size = size || 'small'
- country = country || 'finland'
- hasIce = hasIce || false
- }
可以用以下3个方法改进:
- function getCoffee(customOptions) {
- const defaultOptions = {
- type: 'cappuccino',
- size: 'small',
- country: 'finland',
- hasIce: false
- }
-
- const options = Object.assign(defaultOptions, customOptions)
- }
-
- function getCoffee(options = {}) {
- const {
- type = 'cappuccino',
- size = 'small',
- country = 'finland',
- hasIce = false
- } = options
- }
-
- function getCoffee({
- type = 'cappuccino',
- size = 'small',
- country = 'finland',
- hasIce = false
- } = {}) {
- }
老实说,我也喜欢switch
,但我其实并不知道什么时候使用switch
语句和对象字面量。我依靠直觉来判断该选哪一个。
例如:
- let drink
- switch(type) {
- case 'cappuccino':
- drink = 'Cappuccino';
- break;
- case 'flatWhite':
- drink = 'Flat White';
- break;
- case 'espresso':
- drink = 'Espresso';
- break;
- default:
- drink = 'Unknown drink';
- }
可以改进为:
- const menu = {
- 'cappuccino': 'Cappuccino',
- 'flatWhite': 'Flat White',
- 'espresso': 'Espresso',
- 'default': 'Unknown drink'
- }
-
- const drink = menu[type] || menu['default']
我不知道如何创建好的抽象,但我知道我创建了很多坏的抽象。
凡是皆有两面性。为了减少代码重复,我们牺牲了改变需求的能力。这不是一笔好的交易。——Dan Abramov
下面的代码用于获取订单,且我使用了Redux进行状态管理。这就是样板!!!如果我们在匆忙之下创建了这样的抽象:
获取订单
- // Action Type
- const FETCH_ORDERS_START = "FETCH_ORDERS_START";
- const FETCH_ORDERS_SUCCESS = "FETCH_ORDERS_SUCCESS";
- const FETCH_ORDERS_FAILED = "FETCH_ORDERS_FAILED"
- // Action
- export const fetchOrder = (token) => {
- return dispatch => {
- dispatch(fetchOrdersStart);
- axios.get('/orders.json?auth=' + token).then(res => {
- dispatch(fetchOrdersSuccess(res));
- }).catch(err => {
- dispatch(fetchOrdersFailed(err));
- });
- };
-
- }
-
- export const fetchOrdersSuccess = (orders) => {
- return {
- type: FETCH_ORDERS_SUCCESS,
- orders: orders,
- };
- };
-
- export const fetchOrdersFailed = (error) => {
- return {
- type: FETCH_ORDERS_FAILED,
- error: error,
- };
- };
-
- export const fetchOrdersStart = () => {
- return {
- type: FETCH_ORDERS_START,
- };
- };
我敢打赌你必须得阅读完所有的代码才能理解该抽象。所以应该这样改进:
- // Action
- const moduleName = 'order'
- const path = '/order'
-
- const {moduleActionTypes, moduleActions} = useModuleActions(moduleName, path)
-
- function fetchOrder() {
- moduleActionTypes.getModel()
- }
-
- function updateOrder(data) {
- moduleActionTypes.updateModel(data)
- }
感谢阅读!如果你觉得文章写的对你有帮助的话,也欢迎分享给你的朋友!
每日分享前端插件干货,欢迎关注!