JavaScript 高级单行代码详解

开发 前端
今天我们一起来了解一下关于JavaScript 的高级单行代码的详细解析。

1. 通过键对对象数组进行分组

我们定义了一个名为 groupBy 的函数,它以一个对象数组和一个键作为参数。该函数的目的是将数组中的对象按指定的键进行分组。

const groupBy = (arr, key) =>
arr.reduce(
(acc, obj) => ({ ...acc, [obj[key]]: [...(acc[obj[key]] || []), obj] }),
{}
)


const people = [
{ name: "Alice", age: 21 },
{ name: "Bob", age: 22 },
{ name: "Charlie", age: 21 },
{ name: "David", age: 23 },
{ name: "Eve", age: 22 }
]


console.log(groupBy(people, "age"))


/* Output:
{
21: [
{ name: "Alice", age: 21 },
{ name: "Charlie", age: 21 }
],
22: [
{ name: "Bob", age: 22 },
{ name: "Eve", age: 22 }
],
23: [{ name: "David", age: 23 }]
}
*/

acc 参数是累加分组对象的累加器。obj 参数表示数组中的每个对象。

在 reduce() 方法内部,使用扩展运算符 (...acc) 返回一个新对象。这将创建 accumulator 对象的浅表副本,以便可以在不更改原始对象的情况下对其进行修改。

新对象的属性设置为与 key 参数的值相匹配的键。该属性的值是一个包含被迭代对象的数组。

(acc[obj[key]] || []) 表达式检查该属性是否存在于累加器对象中。如果不存在,则返回一个空数组。展开运算符用于将数组与正在迭代的当前对象连接起来。

最后,groupBy() 函数返回包含分组对象的累加器对象。

2. 返回数组的中位数

我们实现了一个名为 median 的函数,它将一个数字数组作为输入,按升序对其进行排序,并返回排序后的数组的中值。

当数组的元素个数为奇数时,排序数组的中值就是中间的元素。当数组元素个数为偶数时,中值取中间两个元素的平均值。

const median = (arr) => {
const sorted = arr.sort()
const middle = Math.floor(sorted.length / 2)
return sorted.length % 2 === 0
? (sorted[middle - 1] + sorted[middle]) / 2
: sorted[middle]
}


const oddArr = [3, 1, 4, 2, 5]
console.log(median(oddArr)) // 3


const evenArr = [1, 2, 5, 6]
console.log(median(evenArr)) // 3.5

第一个例子,输入数组[3, 1, 4, 2, 5]被排序为[1, 2, 3, 4, 5],中间元素为3。因此,输入数组的中值 是 3。

在第二个例子中,输入数组[1,2,5,6]被排序为[1,2,5,6],中间两个元素为2和5。因此,输入数组的中值为 (2 + 5) / 2 = 3.5。

3.返回数组的模式

数组的众数是数组中出现频率最高的值。如果有多个值具有相同的最高频率,则所有这些值都被视为众数。

const mode = (arr) => {
const counts = arr.reduce(
(acc, curr) => ({ ...acc, [curr]: (acc[curr] || 0) + 1 }),
{}
)


const maxCount = Math.max(...Object.values(counts))


return Object.keys(counts)
.filter((key) => counts[key] === maxCount)
.map(Number)
}


const arr1 = [1, 2, 3, 2, 4, 2, 5]
console.log(mode(arr1)) // [2]


const arr2 = [1, 2, 3, 2, 4, 4, 5]
console.log(mode(arr2)) // [2, 4]

在第一个示例中,输入数组 [1, 2, 3, 2, 4, 2, 5] 的计数为 { 1: 1, 2: 3, 3: 1, 4: 1, 5: 1 }。最高计数为 3,出现值 2。因此,输入数组的模式为 [2]。

在第二个示例中,输入数组 [1, 2, 3, 2, 4, 4, 5] 的计数为 { 1: 1, 2: 2, 3: 1, 4: 2, 5: 1 }。最高计数为 2,出现在值 2 和 4 中。因此,输入数组的模式为 [2, 4]。

4. 使用扩展运算符和 Array.from 创建一个长度为 n 的数组

使用扩展运算符和 Array.from() 创建一个长度为 n 的新数组。生成的数组包含从 0 到 n-1 的升序排列的数字。

const n = 5
const arr = [...Array.from({ length: n }, (_, index) => index)]


console.log(arr) // [ 0, 1, 2, 3, 4 ]

在此示例中,n 设置为 5,因此,生成的数组 arr 的长度为 5。数组的值是使用函数 (_, index) => index 生成的,该函数返回数组的当前索引。因此,结果数组将为 [0, 1, 2, 3, 4]。

5. 使用解构获取数组的最后一个元素

此函数的目的是使用解构获取数组的最后一个元素。

const last = (arr) => [...arr].pop()


const people = [
{ name: "Alice", age: 21 },
{ name: "Bob", age: 22 },
{ name: "Charlie", age: 21 },
{ name: "David", age: 23 },
{ name: "Eve", age: 22 }
]


console.log(last(people)) // { name: "Eve", age: 22 }

在 last() 函数内部,展开运算符 (...) 用于创建原始数组的副本。这是必需的,因为 pop() 方法会修改原始数组并返回删除的元素。

然后,对数组的副本调用 pop() 方法,删除并返回数组的最后一个元素。由于在调用 pop() 方法之前复制了数组,因此不会修改原始数组。

last() 函数返回数组的最后一个元素。

6. 使用布尔构造函数检查变量是否为真

我们函数的目的是使用布尔构造函数检查变量是否为真。

布尔构造函数是 JavaScript 中的一个内置函数,可将值转换为布尔值。如果该值为 truthy,则布尔构造函数返回 true。如果该值为 falsy,则布尔构造函数返回 false。

const isTruthy = (val) => Boolean(val)


console.log(isTruthy(false)) // false
console.log(isTruthy(0)) // false
console.log(isTruthy(-0)) // false
console.log(isTruthy(0n)) // false
console.log(isTruthy("")) // false
console.log(isTruthy(null)) // false
console.log(isTruthy(undefined)) // false
console.log(isTruthy(NaN)) // false


console.log(isTruthy(true)) // true
console.log(isTruthy({})) // true
console.log(isTruthy([])) // true
console.log(isTruthy(42)) // true
console.log(isTruthy("0")) // true
console.log(isTruthy("false")) // true
console.log(isTruthy(new Date())) // true
console.log(isTruthy(Infinity)) // true

7. 从数组中删除虚假值

布尔构造函数用作 filter() 方法的回调函数。如果值为真,则布尔构造函数返回真,如果值为假,则返回假。因此,filter() 方法从原始数组中删除所有虚假值。

const compact = (arr) => arr.filter(Boolean)


const falsyArr = [false, 0, -0, 0n, "", null, undefined, NaN]
const mixArr = [true, false, {}, 0, [], "", "0", null, "false", undefined, 42]


console.log(compact(falsyArr)) // []
console.log(compact(mixArr)) // [ true, {}, [], '0', 'false', 42 ]

在 compact() 函数内部,使用布尔构造函数作为回调函数对 arr 参数调用 filter() 方法。这将返回一个新数组,其中仅包含原始数组的真值。

compact() 函数返回新数组。

当执行 console.log() 语句时,compact(falsyArr) 的输出是一个空数组,因为 falsyArr 数组中的所有值都是假的。compact(mixArr) 的输出是一个数组,它只包含 mixArr 数组的真实值,即 true、一个空对象 {}、一个空数组 []、字符串“0”、字符串“false”,以及 数字 42。所有虚假值(false、0、""、null、undefined 和 NaN)都已从 mixArr 数组中删除。

8. 将字符串数组转换为数字

函数的目的是将字符串数组转换为数字数组。Number 构造函数用作 map() 方法的回调函数。Number 构造函数将字符串转换为数字。

const toNumbers = (arr) => arr.map(Number)


const strArr = ["1", "2", "3", "4", "5"]


console.log(toNumbers(strArr)) // [ 1, 2, 3, 4, 5 ]

在 toNumbers() 函数内部,使用 Number 构造函数作为回调函数对 arr 参数调用 map() 方法。这将返回一个包含转换值的新数组。

9. 返回一个键值翻转的对象

此函数的目的是返回一个新对象,其中翻转了原始对象的键和值。

Object.entries() 方法用于从原始对象创建键值对数组。然后使用 map() 方法迭代数组中的每个键值对,并返回一个新的翻转键值对数组。最后,使用 Object.fromEntries() 方法从翻转的键值对数组中创建一个新对象。

const flip = (obj) =>
Object.fromEntries(Object.entries(obj).map(([key, value]) => [value, key]))


const myDog = {
firstName: "oscar",
lastName: "king",
age: 3
}


console.log(flip(myDog)) // { 3: 'age', oscar: 'firstName', king: 'lastName' }

在 flip() 函数内部,对 obj 参数调用 Object.entries() 方法以创建键值对数组。然后,在键值对数组上调用 map() 方法。对于每个键值对,map() 方法解构键和值变量,并返回一个新数组,其中值作为第一个元素,键作为第二个元素。这将创建一个翻转的键值对数组。

最后,在翻转的键值对数组上调用 Object.fromEntries() 方法以使用翻转的键值对创建一个新对象。

flip() 函数返回新对象。

执行 console.log() 语句时,输出是一个新对象,其中翻转了原始 myDog 对象的键和值。firstName 键及其值“oscar”已翻转为“oscar”键及其值“firstName”。lastName 键及其值“king”已翻转为“king”键及其值“lastName”。age 键及其值 3 已翻转为 3 键及其值“age”。

10. 返回一个只有特定键的对象

此函数的目的是返回一个新对象,该对象仅包含原始对象中指定的键及其对应的值。

const pick = (obj, keys) =>
Object.fromEntries(
Object.entries(obj).filter(([key]) => keys.includes(key))
)


const myDog = {
firstName: "oscar",
lastName: "king",
age: 3
}


console.log(pick(myDog, [])) // {}
console.log(pick(myDog, ["firstName"])) // { firstName: 'oscar' }
console.log(pick(myDog, ["firstName", "lastName"])) // { firstName: 'oscar', lastName: 'king' }

在 pick() 函数内部,对 obj 参数调用 Object.entries() 方法以创建键值对数组。然后,在键值对数组上调用 filter() 方法。对于每个键值对,filter() 方法解构键变量,如果键数组包含键则返回 true。这将创建一个过滤后的键值对数组。

最后,在过滤后的键值对数组上调用 Object.fromEntries() 方法来创建一个仅包含指定键及其对应值的新对象。pick() 函数返回新对象。

11. 返回一个只有唯一值的对象

此函数 uniqueValues 将一个对象作为参数并返回一个新对象,该对象仅包含来自输入对象的唯一值。

const uniqueValues = (obj) =>
Object.fromEntries(
Object.entries(obj).filter(
([key, value], index, entries) =>
entries.findIndex(([k, v]) => v === value) === index
)
)


const myDog = {
id: 3,
firstName: "oscar",
lastName: "oscar",
age: 3
}


console.log(uniqueValues(myDog)) // { id: 3, firstName: 'oscar' }

它首先在输入对象上调用 Object.entries() 方法以获取键值对数组。然后,它使用 filter() 方法过滤条目数组,并仅返回值唯一的条目。

要检查一个值是否唯一,它在原始条目数组上使用 findIndex() 方法。它查找与当前过滤的条目具有相同值的第一个条目的索引。如果当前条目的索引等于第一个匹配条目的索引,则意味着该值是唯一的,应该包含在结果对象中。

最后,它使用 Object.fromEntries() 方法将过滤后的条目数组转换回对象。

在示例代码中,使用具有某些重复值的对象 myDog 调用 uniqueValues 函数。该函数返回一个仅包含唯一值并删除重复值的新对象。生成的对象具有 id:3 和 firstName:'oscar'。

责任编辑:华轩 来源: web前端开发
相关推荐

2022-11-28 23:44:26

JavaScript技巧程序员

2023-02-15 16:19:59

JavaScript技巧API

2022-10-20 15:16:23

JavaScript数组技能

2023-10-10 16:20:38

JavaScript代码技巧

2024-10-09 14:45:41

2022-12-19 15:23:51

JavaScrip开发语言

2023-05-30 15:11:16

JavaScrip开发功能

2023-08-27 16:19:09

JavaScript编程语言

2022-09-02 23:08:04

JavaScript技巧开发

2023-06-14 15:51:48

JavaScript

2022-10-08 07:54:24

JavaScriptAPI代码

2022-10-09 18:52:11

JavaScript开发数组

2024-09-04 14:00:16

2024-07-26 00:00:05

JavaScript单行技巧

2022-12-28 17:20:03

JavaScript解决方案

2024-11-14 08:35:50

JavaScript管道操作符

2023-01-27 15:22:11

JavaScript开发编程语言

2024-08-27 15:25:33

2021-04-19 11:30:06

Java开发程序

2021-04-21 07:53:12

JavaScript单行程序
点赞
收藏

51CTO技术栈公众号