英文 | https://blog.logrocket.com/16-useful-typescript-javascript-shorthands-know/
翻译 | 杨小爱
JavaScript 和 TypeScript 共享许多有用的常用代码概念的技巧替代方案。这些代码替代方案可以帮助减少代码行数,这也是我们努力的目标。
在本文中,我们将分享 16 个常见的 TypeScript 和 JavaScript 技巧。我们还将探讨如何使用这些速记的示例。
在编写干净且可扩展的代码时,使用这些技巧并不总是正确的决定。简洁的代码有时会更容易阅读和更新。我们的代码必须清晰易读,并向其他开发人员传达含义和上下文,这一点也很重要。
JavaScript 中可用的所有技巧都可以在 TypeScript 中以相同的语法使用。唯一的细微差别是在 TypeScript 中指定类型。但是,TypeScript 构造函数简写是 TypeScript 独有的。
现在,我们就正式开始吧。
01、三元运算符
三元运算符是 JavaScript 和 TypeScript 中最流行的简写之一。它取代了传统的 if…else 语句。它的语法如下:
代码语言:javascript复制[condition] ? [true result] : [false result]
以下示例演示了传统的 if...else 语句及其使用三元运算符的等效简写:
代码语言:javascript复制// Longhand
const mark = 80
if (mark >= 65) {
return "Pass"
} else {
return "Fail"
}
// Shorthand
const mark = 80
return mark >= 65 ? "Pass" : "Fail"
02、短路评估
替换 if...else 语句的另一种方法是使用短路评估。此技巧使用逻辑 OR 运算符 || 当预期值是虚假的时,为变量分配默认值。
以下示例演示了如何使用短路评估:
代码语言:javascript复制// Longhand
let str = ''
let finalStr
if (str !== null && str !== undefined && str != '') {
finalStr = str
} else {
finalStr = 'default string'
}
// Shorthand
let str = ''
let finalStr = str || 'default string' // 'default string
03、空值合并运算符
无效的合并运算符 ?? 类似于短路评估,因为它用于为变量分配默认值。但是,空值合并运算符仅在预期值也为空值时使用默认值。
换句话说,如果预期值是虚假的但不是空值,它将不会使用默认值。
以下是空值合并运算符的两个示例:
代码语言:javascript复制// Example 1
// Longhand
let str = ''
let finalStr
if (str !== null && str !== undefined) {
finalStr = 'default string'
} else {
finalStr = str
}
// Shorthand
let str = ''
let finaStr = str ?? 'default string' // ''
// Example 2
// Longhand
let num = null
let actualNum
if (num !== null && num !== undefined) {
actualNum = num
} else {
actualNum = 0
}
// Shorthand
let num = null
let actualNum = num ?? 0 // 0
04、模板文字
借助 JavaScript 强大的 ES6 特性,我们可以使用模板文字而不是使用 来连接字符串中的多个变量。要使用模板文字,请将字符串包装在 `` 中,并将变量包装在这些字符串中的 ${} 中。
下面的示例演示了如何使用模板文字来执行字符串插值:
代码语言:javascript复制const name = 'Iby'
const hobby = 'to read'
// Longhand
const fullStr = name ' loves ' hobby // 'Iby loves to read'
// Shorthand
const fullStr = `${name} loves ${hobby}`
我们还可以使用模板文字来构建多行字符串,而无需使用 n。例如:
代码语言:javascript复制// Shorthand
const name = 'Iby'
const hobby = 'to read'
const fullStr = `${name} loves ${hobby}.
She also loves to write!`
05、对象属性赋值简写
在 JavaScript 和 TypeScript 中,我们可以通过在对象字面量中提及变量来以简写形式将属性分配给对象。为此,必须使用预期的键命名变量。
请参阅下面的对象属性分配简写示例:
代码语言:javascript复制// Longhand
const obj = {
x: 1,
y: 2,
z: 3
}
// Shorthand
const x = 8
const y = 10
const obj = { x, y }
06、可选链接
点表示法允许我们访问对象的键或值。使用可选链接,我们可以更进一步,即使我们不确定它们是否存在或已设置,也可以读取键或值。当键不存在时,来自可选链接的值是未定义的。
请参阅下面的可选链接示例:
代码语言:javascript复制const obj = {
x: {
y: 1,
z: 2
},
others: [
'test',
'tested'
]
}
// Longhand
if (obj.hasProperty('others') && others.length >= 2) {
console.log('2nd value in others: ', obj.others[1])
}
// Shorthand
console.log('2nd value in others: ', obj.others?.[1]) // 'tested'
console.log('3rd value in others: ', obj.others?.[2]) // undefined
07、对象解构
除了传统的点符号之外,另一种读取对象值的方法是将对象的值解构为它们自己的变量。
下面的示例演示了如何使用传统的点表示法读取对象的值,与使用对象解构的速记方法进行比较。
代码语言:javascript复制const obj = {
x: {
y: 1,
z: 2
},
other: 'test string'
}
// Longhand
console.log('Value of z in x: ', obj.x.z)
console.log('Value of other: ', obj.other)
// Shorthand
const {x, other} = obj
const {z} = x
console.log('Value of z in x: ', z)
console.log('Value of other: ', other)
我们还可以重命名从对象中解构的变量。这是一个例子:
代码语言:javascript复制const obj = {x: 1, y: 2}
const {x: myVar} = object
console.log('My renamed variable: ', myVar) // My renamed variable: 1
08、扩展运算符
扩展运算符 ... 用于访问数组和对象的内容。我们可以使用扩展运算符来替换数组函数(如 concat)和对象函数(如 object.assign)。
查看下面的示例,了解如何使用扩展运算符替换普通数组和对象函数。
代码语言:javascript复制// Longhand
const arr = [1, 2, 3]
const biggerArr = [4,5,6].concat(arr)
const smallObj = {x: 1}
const otherObj = object.assign(smallObj, {y: 2})
// Shorthand
const arr = [1, 2, 3]
const biggerArr = [...arr, 4, 5, 6]
const smallObj = {x: 1}
const otherObj = {...smallObj, y: 2}
09、对象循环
传统的 JavaScript for 循环语法如下:
代码语言:javascript复制for (let i = 0; i < x; i ) { … }
我们可以使用这种循环语法通过引用迭代器的数组长度来迭代数组。
共有三种 for 循环简写,它们提供了不同的方式来遍历数组对象:
- for...of 访问数组条目
- for...in 用于访问数组的索引和在对象字面量上使用时的键
- Array.forEach 使用回调函数对数组元素及其索引执行操作
请注意 Array.forEach 回调有三个可能的参数,按以下顺序调用:
- 正在进行的迭代的数组元素
- 元素的索引
- 数组的完整副本
下面的示例演示了这些对象循环简写的作用:
代码语言:javascript复制// Longhand
const arr = ['Yes', 'No', 'Maybe']
for (let i = 0; i < arr.length; i ) {
console.log('Here is item: ', arr[i])
}
// Shorthand
for (let str of arr) {
console.log('Here is item: ', str)
}
arr.forEach((str) => {
console.log('Here is item: ', str)
})
for (let index in arr) {
console.log(`Item at index ${index} is ${arr[index]}`)
}
// For object literals
const obj = {a: 1, b: 2, c: 3}
for (let key in obj) {
console.log(`Value at key ${key} is ${obj[key]}`)
}
10、Array.indexOf 使用按位运算符的简写
我们可以使用 Array.indexOf 方法查找数组中是否存在项目。如果该项目存在于数组中,则此方法返回该项目的索引位置,如果不存在则返回 -1。
在 JavaScript 中,0 是一个假值,而小于或大于 0 的数字被认为是真值。通常,这意味着我们需要使用 if...else 语句来使用返回的索引来确定项目是否存在。
使用按位运算符 ~ 而不是 if...else 语句可以让我们获得大于或等于 0 的任何值的真值。
下面的示例演示了使用按位运算符而不是 if...else 语句的 Array.indexOf 速记:
代码语言:javascript复制const arr = [10, 12, 14, 16]
const realNum = 10
const fakeNum = 20
const realNumIndex = arr.indexOf(realNum)
const noneNumIndex = arr.indexOf(fakeNum)
// Longhand
if (realNumIndex > -1) {
console.log(realNum, ' exists!')
} else if (realNumIndex === -1) {
console.log(realNum, ' does not exist!')
}
if (noneNumIndex > -1) {
console.log(fakeNum, ' exists!')
} else if (noneNumIndex === -1) {
console.log(fakeNum, ' does not exist!')
}
// Shorthand
console.log(realNum (~realNumIndex ? ' exists!' : ' does not exist!')
console.log(fakeNum (~noneNumIndex ? ' exists!' : ' does not exist!')
11、使用 !! 将值转换为布尔值
在 JavaScript 中,我们可以使用 !![variable] 简写将任何类型的变量转换为布尔值。
查看使用 !! 的示例 [变量] 将值转换为布尔值的简写:
代码语言:javascript复制// Longhand
const simpleInt = 3
const intAsBool = Boolean(simpleInt)
// Shorthand
const simpleInt = 3
const intAsBool = !!simpleInt
12、箭头/lambda 函数表达式
JavaScript 中的函数可以使用箭头函数语法来编写,而不是显式使用 function 关键字的传统表达式。箭头函数类似于其他语言中的 lambda 函数。
看看这个使用箭头函数表达式以简写形式编写函数的示例:
代码语言:javascript复制// Longhand
function printStr(str) {
console.log('This is a string: ', str)
}
printStr('Girl!')
// Shorthand
const printStr = (str) => {
console.log('This is a string: ', str)
}
printStr('Girl!')
// Shorthand TypeScript (specifying variable type)
const printStr = (str: string) => {
console.log('This is a string: ', str)
}
printStr('Girl!')
13、使用箭头函数表达式的隐式返回
在 JavaScript 中,我们通常使用 return 关键字从函数中返回一个值。当我们使用箭头函数语法定义函数时,我们可以通过排除大括号 {} 来隐式返回一个值。
对于多行语句,例如表达式,我们可以将返回表达式包裹在括号 () 中。
下面的示例演示了使用箭头函数表达式从函数中隐式返回值的简写代码:
代码语言:javascript复制// Longhand
function capitalize(name) {
return name.toUpperCase()
}
function add(numA, numB) {
return numA numB
}
// Shorthand
const capitalize = (name) => name.toUpperCase()
const add = (numA, numB) => (numA numB)
// Shorthand TypeScript (specifying variable type)
const capitalize = (name: string) => name.toUpperCase()
const add = (numA: number, numB: number) => (numA numB)
14、双位非运算符
在 JavaScript 中,我们通常使用内置的 Math 对象来访问数学函数和常量。但是,一些函数允许我们在不引用 Math 对象的情况下访问函数。
例如,应用按位 NOT 运算符两次 ~~ 允许我们获得一个值的 Math.floor()。
查看下面的示例,了解如何将双位 NOT 运算符用作 Math.floor() 速记:
代码语言:javascript复制// Longhand
const num = 4.5
const floorNum = Math.floor(num) // 4
// Shorthand
const num = 4.5
const floorNum = ~~num // 4
15、指数幂速记
另一个具有用的技巧是 Math.pow() 函数。使用内置 Math 对象的替代方法是 ** 使用技巧。
下面的示例演示了这种指数幂的简写:
代码语言:javascript复制// Longhand
const num = Math.pow(3, 4) // 81
// Shorthand
const num = 3 ** 4 // 81
16、TypeScript 构造函数简写
通过 TypeScript 中的构造函数创建一个类并为类属性赋值有一个简写。使用此方法时,TypeScript 会自动创建和设置类属性。
这个速记是 TypeScript 独有的,在 JavaScript 类定义中不可用。
看看下面的例子,看看 TypeScript 构造函数的简写:
代码语言:javascript复制// Longhand
class Person {
private name: string
public age: int
protected hobbies: string[]
constructor(name: string, age: int, hobbies: string[]) {
this.name = name
this.age = age
this.hobbies = hobbies
}
}
// Shorthand
class Person {
constructor(
private name: string,
public age: int,
protected hobbies: string[]
) {}
}
总结
以上这些只是一些最常用的 JavaScript 和 TypeScript 技巧。请记住,使用这些代码并不总是最好的选择。最重要的是编写其他开发人员可以轻松阅读的简洁易懂的代码。
如过你还有最喜欢的 JavaScript 或 TypeScript 技巧的话,请在评论中与我们分享!
最后,感谢你的阅读,祝编程愉快,如果你觉得有用的话,请记得分享给你身边做开发的朋友,也许能够帮助到他。