突破常规的前端技巧与方法(一)

简介: 突破常规的前端技巧与方法(一)

一、代码整洁推荐

1.1 三元(三目)运算符

如果只想在一行中编写if…else语句时,这是一个很好的节省代码的方式。

常规:

const x = 20
let answer
if(x > 10) {
    answer = '大于10'
}else {
    answer = '小于等于10'
}

简写:

const x = 20
const answer = x > 10? '大于10' : '小于等于10'

嵌套版三元运算

const x = 20
const answer = x > 10? '大于10' : x < 5? '小于5' : '在5和10之间'
// 第二层加上()增强可读性
const answer = x > 10? '大于10' : (x < 5? '小于5' : '在5和10之间')

注意:三元运算不要超过2层嵌套,否则可读性不强,如果是嵌套两层,要求第二层加上()帮助提升可读性。

1.2 短路判断简写

将变量值分配给另一个变量时,可能希望确保源变量不为null,undefined或为空。这时候可以编写带有多个条件的长 if 语句,也可以使用短路判断。

常规:

if(type !== null || type !== undefined || type !== '') {
    let wtType = type
} else {
    let wtType = '01'
}

简写:

let wtType = type || '01'

注意:如果type值为false或者数字0将取值为字符串’01’。

1.3 变量声明简写

在进行连续性的变量声明操作时,应尽可能的使用 一次声明语句来提升程序运行效率。

常规:

let x
let y
let z = 1

简写:

let x, y, z = 1

1.4 if真值判断简写

这可能是微不足道的,但值得一提。在执行“if 检查”时,有时可以省略全等运算符。

常规:

if(likeJavascript === true) {
    ...
}
if(likeNode !== true) {
    ...
}

简写:

if(likeJavascript) {
    ...
}
if(!likeNode) {
    ...
}

1.5 For循环简写

常规:

const arr = [1, 2, 3]
for(let i = 0; i < arr.length; i++) {
  console.log(i, arr[i])
  if(arr[i] > 1) {
    break
  }
}
// 0, 1
// 1, 2

如果不需要访问索引,请执行以下操作:

for(let item of arr) {
  console.log('item', item)
  if(item > 1) {
        break
    }
}
// 1
// 2

如果只想访问索引,请执行以下操作:

for(let index in arr) {
    console.log(index)
}
// 1
// 2
// 3

如果要访问对象中的键,请执行以下操作

const obj = {name: 'zhangsan', age: 18}
for(let key in obj) {
    console.log(key,obj[key])
}
// name
// age

注意:不能使用for…of 来遍历对象

1.6 对象属性简写

ES6提供了一种更简单的方法来为对象分配属性。如果变量名称与对象键相同,则可以使用简写表示法。

常规:

let signType = '1'
let params = {
    signType: signType
}

简写:

let signType = '1'
let params = {
    signType
}

1.7 箭头函数简写

经典函数以简单的形式易于读写,但是一旦你开始将它们嵌套在其他函数调用中,它们往往会变得有点冗长和混乱。

常规:

function sayHello(name) {
    console.log('Hello', name)
}
setTimeout(function() {
  console.log('Loaded')
}, 2000)
list.forEach(function(item) {
    console.log(item)
})

简写:

const sayHello = name => console.log('Hello', name)
setTimeout(() => console.log('Loaded'), 2000)
list.forEach(item => console.log(item))

1.8 隐式返回简写

Return 是我们经常使用的关键字,用于返回函数的最终结果。具有单个语句的箭头函数将隐式返回其执行结果(函数可以省略大括号{}用()省略return关键字,具体可参考下例)。

要返回多行语句(例如对象),必须使用 () 而不是 {} 来包装函数体。这可确保将代码执行为单个语句。

常规:

function sum(x, y) {
   return x + y
}
function makeInfo(name, age) {
    return {name, age}
}

简写:

const sum = (x, y) => x + y
const makeInfo = (name, age) => ({name, age})

1.9 模板字符串

您是否厌倦了使用 ‘+’ 将多个变量连接成一个字符串?有没有更简单的方法?如果你能够使用ES6,那么你很幸运。您需要做的就是使用反引号,并使用 ${} 来包含变量。

常规:

const name = 'zhangsan'
const age = 18
let des = name + '今年' + age + '岁'

简写:

const name = 'zhangsan'
const age = 18
let des = `${name}今年${age}岁`

1.10 默认参数值

您可以使用if语句定义函数参数的默认值。在ES6中,您可以在函数声明本身中定义默认值。

常规:

function volume(l, w, h) {
    if(w === undefined) {
        w = 3
    }
    if(h === undefined) {
        h = 4
    }
    return l * w * h
}

简写:

const volume = (l, w = 3, h = 4) => l * w * h
volume(2)
// 24

注意:只有w,h为undefined时默认值才会生效。

结构赋值中的默认值也是如此,如果值为null默认值不会生效,如:

const res = {
    list: null,
    code: undefined
}
const { list = [], code = 1 } = res
console.log(list) // null
console.log(code) // 1
let num = list.length // Uncaught TypeError: Cannot read properties of null (reading 'length')

注意:如果直接取list数组的长度或者利用[index]取里面的值在res.list为null或者不为数组的时候可能会发生报错,针对该问题,大家可以在解构的时候不赋默认值,在解构的下方利用null判断运算符来处理默认值,如:

const res = {
    list: null
}
let { list , code = 1 } = res
list = list ?? []
console.log(list) // []
let num = list.length // 0

1.11 解构赋值简写

对数组和变量进行解构可以减少变量滥用,提升程序的运行效率。

常规:

let params = {
  wtId: this.transferDetail.wtId,
  newPic: type === '01' ? this.selectPersonId : '', // type是方法入参
  oldPic: this.transferDetail.picOld,
  recordId: this.applyId, // 转派记录
  replacementPicStatus: '02', // 转派状态 01-转派中 02-转派结束
  replacementReason: this.replacementReason
}

简写:

const { selectPersonId, applyId, replacementReason, transferDetail } = this
let params = {
  wtId: transferDetail.wtId,
  newPic: type === '01' ? selectPersonId : '', // type是方法入参
  oldPic: transferDetail.picOld,
  recordId: applyId, // 转派记录
  replacementPicStatus: '02', // 转派状态 01-转派中 02-转派结束
  replacementReason
}

解构知识点链接地址:https://es6.ruanyifeng.com/#docs/destructuring

1.12 多条件判断简写

常规:

function typeHandle(type) {
    if (type === 'test1') {  
        test1(); 
     } else if (type === 'test2') {  
        test2(); 
     } else if (type === 'test3') {  
        test3(); 
     } else if (type === 'test4') {  
        test4(); 
     } else {  
        throw new Error('Invalid value ' + type); 
     }  
}
typeHandle('test3')

简写:

function typeHandle(type) { 
    const types = {  
         test1: test1,  
         test2: test2,  
         test3: test3,  
         test4: test4 
     }; 
    let func = types[type]; 
    (!func) && throw new Error('Invalid value ' + type);
    func(); 
}
typeHandle('test3')

1.13 多变量赋值简写

常规:

let test1, test2, test3; 
test1 = 1; 
test2 = 2; 
test3 = 3; 
let name, age, sex;
name = 'zhangsan';
age = '18';
sex = '男'

简写:(利用es6数组、对象的结构赋值,实现多变量赋值简写)

let [test1, test2, test3] = [1, 2, 3]; 
let {name, age, sex} = { name: 'zhangsan', age: '18', sex: '男'};

1.14 解构时重命名

常规:

const { ticketTypeName } = this.tciketDetail
let params = {
    wtName: ticketTypeName,
    ...
}

简写:

const { ticketTypeName: wtName } = this.tciketDetail
let params = {
    wtName,
    ...
}

对象解构赋值的简写形式:

let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };

也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined

1.15 对象替代switch

常规:

// 获取工作票名称
workTicketName(type) {
    switch (type) {
        case '01':
            return '变一'
            break
        case '02':
            return '变二'
            break
        case '03':
            return '配一'
            break
        case '04':
            return '配二'
            break
        case '05':
            return '低压'
            break
        case '06':
            return '作业卡'
            break
        case '07':
            return '派工单'
            break
        default:
            break
    }
}
workTicketName('01') // 变一

简写:

// 获取工作票名称
workTicketName(type) {
    const typeObj = {
        '01': '变一',
        '02': '变二',
        '03': '配一',
        '04': '配二',
        '05': '低压',
        '06': '作业卡',
        '07': '派工单'
    }
    return typeObj[type]
}
workTicketName('01') // 变一

1.16 链判断运算符

编程实务中,如果读取对象内部的某个属性,往往需要判断一下,属性的上层对象是否存在。比如,读取message.body.user.firstName这个属性,安全的写法是写成下面这样。

// 错误的写法
const  firstName = message.body.user.firstName || 'default';
// 正确的写法
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';
// 但是这种写法如果层级过长会显得冗长,可读性也不强,这是我们可以利用链判断运算符来解决
//链判断运算符写法
const firstName = message?.body?.user?.firstName || 'default';

链判断运算符?.有三种写法。

  • obj?.prop // 对象属性是否存在
  • obj?.[expr] // 同上 也可以理解为 arr?.[index]
  • func?.(...args) // 函数或对象方法是否存在

下面是?.运算符常见形式,以及不使用该运算符时的等价形式。

a?.b
// 等同于
a == null ? undefined : a.b
a?.[x]
// 等同于
a == null ? undefined : a[x]
a?.b()
// 等同于
a == null ? undefined : a.b()
a?.()
// 等同于
a == null ? undefined : a()

常规:

// 计划 id
let planId = this.ticketDetail && this.ticketDetail.planDetailVoList && this.ticketDetail.planDetailVoList[0] && this.ticketDetail.planDetailVoList[0].planId

简写:

// 计划 id
let planId = this.ticketDetail?.planDetailVoList?.[0]?.planId 
// 如果任意一个问号前面的值为null或者undefined都将直接返回undefined,不在向下取值

注意:链判断运算符只能在js代码块中使用,不能在template里面的标签上使用,否则会解析报错,如果想要在template里达到上述简写效果可以在计算属性中使用。

// 错误的写法
<template>  
    <div class="wrap">   
        <span>计划编号:</span>
        {{
              ticketDetail && ticketDetail.planDetailVoList && ticketDetail.planDetailVoList[0] && ticketDetail.planDetailVoList[0].planNo || ''
        }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                ticketDetail: {
                    planDetailVoList: [
                        {
                            planNo: 'T202304200940' // 计划编号
                        }
                    ]
                } 
            }  
        }
    } 
</script>
//正确的写法
<template>  
    <div class="wrap">   
        <span>计划编号:</span>
        {{ planNo }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                ticketDetail: {
                    planDetailVoList: [
                        {
                            planNo: 'T202304200940' // 计划编号
                        }
                    ]
                } 
            }  
        },
        // 计算属性
        computed: {
            // 计划编号
            planNo({ticketDetail}) {
               return ticketDetail?.planDetailVoList?.[0]?.planNo || ''
            }
        }
    } 
</script>

链判断运算符知识点链接:https://es6.ruanyifeng.com/#docs/operator

1.17 Null 判断运算符

读取对象属性的时候,如果某个属性的值是nullundefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

const headerText = response.settings.headerText || 'Hello, world!';
const animationDuration = response.settings.animationDuration || 300;
const showSplashScreen = response.settings.showSplashScreen || true;

上面的三行代码都通过||运算符指定默认值,但是这样写是错的。开发者的原意是,只要属性的值为nullundefined,默认值就会生效,但是属性的值如果为空字符串或false0,默认值也会生效。

为了避免这种情况,ES2020 引入了一个新的 Null 判断运算符??。它的行为类似||,但是只有运算符左侧的值为nullundefined时,才会返回右侧的值。

const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;

上面代码中,默认值只有在左侧属性值为nullundefined时,才会生效。

目录
相关文章
|
2月前
|
前端开发
前端接受后端文件流并下载到本地的方法
前端接受后端文件流并下载到本地的方法
60 0
|
4月前
|
人工智能 前端开发 测试技术
AI:探究下前端组件化设计的实现方法及其重要性(一)
AI:探究下前端组件化设计的实现方法及其重要性
|
4月前
|
人工智能 缓存 前端开发
AI:探究下前端组件化设计的实现方法及其重要性(二)
AI:探究下前端组件化设计的实现方法及其重要性
|
4月前
|
前端开发 JavaScript API
微前端:一种新型的前端架构方法
微前端:一种新型的前端架构方法
98 0
|
4月前
|
前端开发 JavaScript API
[前端面试题]:数组去重的几种方法
[前端面试题]:数组去重的几种方法
|
2天前
|
前端开发 JavaScript 开发者
【Web 前端】数组迭代的方法有哪些?
【4月更文挑战第22天】【Web 前端】数组迭代的方法有哪些?
|
2天前
|
前端开发
【Web 前端】对于数组去重都有哪些方法?
【4月更文挑战第22天】【Web 前端】对于数组去重都有哪些方法?
|
2天前
|
前端开发 JavaScript
【Web 前端】JS继承的方法有哪些?
【4月更文挑战第22天】【Web 前端】JS继承的方法有哪些?
|
2天前
|
前端开发 JavaScript UED
【Web 前端】说几个未知宽高元素水平垂直居中方法?
【4月更文挑战第22天】【Web 前端】说几个未知宽高元素水平垂直居中方法?
|
3天前
|
前端开发 容器
【Web 前端】清除浮动有哪些方法?
【4月更文挑战第22天】【Web 前端】清除浮动有哪些方法?