壹、IIFE 立即调用函数表达式 🕦 🕦 🕦 🕦
IIFE(立即调用函数表达式)是一个在定义时就会立即执行的 JavaScript 函数。这个本不应该出现在这里,懒得拿出来单独重新写,就放这里吧。下面是在vue3中的一个demo。
demo中可以发现它在vue3中的优先级高于onBeforeMount,所以你可以用它做一些特殊的业务处理🎃🎃🎃🎃
<script lang="ts">
export default defineComponent({
setup() {
(function(){
console.log('立即调用函数表达式11111')
})()
onBeforeMount(() => {
console.log('组件挂载到节点上之前执行的函数')
});
!function() {
console.log('立即调用函数表达式22222')
return ''
}();
onMounted(() => {
console.log('组件挂载完成后执行的函数;')
});
(function(){
console.log('立即调用函数表达式33333')
}());
}
})
</script>
贰、&&、&&= 🕐 🕐 🕐 🕐
&&当且仅当其所有操作数都为真时
&&= 逻辑 AND 赋值 ( x &&= y) 运算符仅在x为真时才赋值。
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
info1: {
name: 'Etc.End',
age: 28,
gender: '男',
weChat: 'SH--TS',
state: 1,
enable: true,
},
info2: {
name: 'Annie',
age: 28,
gender: '',
weChat: 'SH--TS',
state: 0,
enable: false,
}
})
// 记住在js中0为false, 其他都为true
if (data.info1.state && data.info2.state) {
console.log('不会通过校验!!!')
}
// 这里是因为info2中的状态为0
// !data.info2.state是取反
// 即data.info2.state为false 所以!data.info2.state 就为 true
if (data.info1.state && !data.info2.state) {
console.log('通过校验!!!')
}
// 正常的写法
if (data.info1.enable) {
data.info1.age = 18
console.log(JSON.stringify(data.info1))
// {"name":"Etc.End","age":18,"gender":"男","weChat":"SH--TS","state":1,"enable":true}
}
// 使用运算符&&进行短路运算
// 仅在&&左侧为真时,才会执行右侧的代码逻辑
data.info1.enable && (data.info1.age = 20)
console.log(JSON.stringify(data.info1))
// {"name":"Etc.End","age":20,"gender":"男","weChat":"SH--TS","state":1,"enable":true}
// 正常的写法
if (data.info1.gender) {
data.info1.gender = '男性'
console.log(JSON.stringify(data.info1))
// {"name":"Etc.End","age":20,"gender":"男性","weChat":"SH--TS","state":1,"enable":true}
}
// 使用运算符&&=再进行简化
data.info1.gender &&= '男性同胞'
console.log(JSON.stringify(data.info1))
// {"name":"Etc.End","age":20,"gender":"男性同胞","weChat":"SH--TS","state":1,"enable":true}
}
})
</script>
叁、||、||= 🕜 🕜 🕜 🕜
|| 当且仅当其一个或多个操作数为真时,一组操作数的逻辑 OR ( ||) 运算符(逻辑析取)为真。
||= 逻辑或赋值(x ||= y)运算仅在 x 为虚值时赋值。
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
info1: {
name: 'Etc.End',
age: 28,
gender: '男',
weChat: 'SH--TS',
state: 1,
enable: true,
},
info2: {
name: 'Annie',
age: 28,
gender: '',
weChat: 'SH--TS',
state: 0,
enable: false,
}
})
// 记住在js中0为false, 其他都为true
// 正常的写法
if (!data.info2.state) {
data.info2.gender = '男'
console.log(JSON.stringify(data.info2))
// {"name":"Annie","age":28,"gender":"男","weChat":"SH--TS","state":0,"enable":false}
}
// 使用运算符||进行短路运算
// 仅在||左侧为假时,才会执行右侧的代码逻辑
data.info2.state || (data.info2.gender = '男性')
console.log(JSON.stringify(data.info2))
// {"name":"Annie","age":28,"gender":"男性","weChat":"SH--TS","state":0,"enable":false}
// 正常的写法
if (!data.info2.state) {
data.info2.state = data.info1.state
console.log(JSON.stringify(data.info1))
// {"name":"Etc.End","age":28,"gender":"男","weChat":"SH--TS","state":1,"enable":true}
}
// 使用运算符||=再进行简化
data.info1.gender = '男性一枚'
data.info2.gender = ''
data.info2.gender ||= data.info1.gender
console.log(JSON.stringify(data.info2))
// {"name":"Annie","age":28,"gender":"男性一枚","weChat":"SH--TS","state":1,"enable":false}
}
})
</script>
肆、??、??= 🕙 🕙 🕙 🕙
空值合并运算符(??)是一个逻辑运算符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
与逻辑或运算符(||)不同,逻辑或运算符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,'' 或 0)时。见下面的例子。
逻辑空赋值运算符(x ??= y)仅在 x 是空值(null 或 undefined)时对其赋值。
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
count: 22,
count1: null,
})
// 记住在js中0为false, 其他都为true
data.count = data.count ?? 10
data.count1 = data.count1 ?? 10
console.log(data.count)
// 22
console.log(data.count1)
// 10
// 恢复默认值
data.count = 22
data.count1 = null
data.count ??= 10
data.count1 ??= 10
console.log(data.count)
// 22
console.log(data.count1)
// 10
}
})
</script>
伍、?. 🕥 🕥 🕥 🕥
可选链运算符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。 当尝试访问可能不存在的对象属性时,可选链运算符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链运算符也是很有帮助的。
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
info: {
name: 'Etc.End',
age: 28,
gender: '男',
weChat: 'SH--TS',
state: 1,
enable: true,
more: {
address: '云南省昆明市'
},
list: [1, 2, 3, 4, 5, 6, 7]
}
})
// 虽然info不包含interest这个对象,但这里不会报错,因为使用?.会进行短路求值
if (data.info?.interest?.football == 100) {
console.log(123)
}
// 这里就会报错,因为使用.不会进行短路操作。
// if (data.info.interest.football == 100) {
// console.log(123)
// }
console.log(data.info?.more?.['address']) // 云南省昆明市
// ?. 除了用于object,还可以用于array和function
console.log(data.info?.list?.[1]) // 2
console.log(data.info?.list?.[7]) // undefined
// 结合??的使用
const name = data.info?.name ?? 'tiger'
console.log(name) // Etc.End
}
})
</script>
陆、~~ 🕚 🕚 🕚 🕚
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
value: 0.123456,
value1: 3.1415926,
value2: -10.258,
value3: 4.4,
value4: 4.5,
value5: 4.6,
value6: -4.4,
value7: -4.5,
value8: -4.6,
value9: true,
value10: false,
value11: [],
value12: '',
value13: {},
})
console.log(~~data.value) // 0
console.log(~~data.value1) // 3
console.log(~~data.value2) // -10
console.log(~~data.value3) // 4
console.log(~~data.value4) // 4
console.log(~~data.value5) // 4
console.log(~~data.value6) // -4
console.log(~~data.value7) // -4
console.log(~~data.value8) // -4
console.log(~~data.value9) // 1
console.log(~~data.value10) // 0
console.log(~~data.value11) // 0
console.log(~~data.value12) // 0
console.log(~~data.value13) // 0
}
})
</script>
柒、... 🕚 🕚 🕚 🕚
展开语法 (Spread syntax), 可以在函数调用/数组构造时,将数组表达式或者 string 在语法层面展开;还可以在构造字面量对象时,将对象表达式按 key-value 的方式展开。(译者注: 字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 这种简洁的构造方式)
<script lang="ts">
export default defineComponent({
setup() {
let data = reactive({
value: 1,
list: [1, 2, 3, 4],
list1: [4, 5, 6, 7],
obj: {
name: 1,
sex: 2
},
obj2: {
iphone: '3'
}
})
console.log(...data.list) // 1 2 3 4
// 接收任意个参数
const fun = (...x: any) => {
console.log(x) // [1, 2, 3, 4]
}
fun(...data.list)
console.log([...data.list, 'hello', ...'hello', 5])
// [1, 2, 3, 4, 'hello', 'h', 'e', 'l', 'l', 'o', 5]
// 克隆或者属性拷贝
const newData = {...data}
console.log(JSON.stringify(newData))
// {"value":1,"value1":2,"value2":3,"list":[1,2,3,4]}
// 下面的语句发现data发生了变化,但是newData不受影响
data.value = 100
console.log(JSON.stringify(data))
// {"value":100,"value1":2,"value2":3,"list":[1,2,3,4]}
// 合并两个数组,之前会用到concat
console.log(data.list.concat(data.list1))
// [1, 2, 3, 4, 4, 5, 6, 7]
// 优雅一点,这里如果之前没有了解过展开语法的话,会看得很懵
console.log([...data.list, ...data.list1])
// [1, 2, 3, 4, 4, 5, 6, 7]
// 合并除了针对数组,还可以作用到对象上面,一样的效果
const obj1 = {...data.obj}
console.log(obj1)
// {name: 1, sex: 2}
console.log({...data.obj, ...data.obj2})
// {name: 1, sex: 2, iphone: '3'}
}
})
</script>