优秀的编程知识分享平台

网站首页 > 技术文章 正文

JavaScript 中的 4 种新方法指南Array.

nanyue 2025-01-02 18:09:56 技术文章 5 ℃

JavaScript 中的 4 种新方法指南Array.prototype

Array其实和Python中的l列表list的操作用非常像

JavaScript 语言标准的最新版本是 ECMAScript 2023,这是第 14 版。此更新包括原型上的新方法。Array

我将指导您了解本文中突出的四种新方法,包括它们在稀疏数组和类数组对象中的行为。如果你喜欢编写JavaScript程序的声明式、函数式风格,那么你将大饱口福。

潜入:

  • 保留没有任何突变的原始阵列重要吗?
  • toReversed() 方法
  • toSorted() 方法
  • toSpliced(start, deleteCount, ...项)方法
  • with(index, value) 方法

保留没有任何突变的原始阵列重要吗?

四种新数组方法的一个共同主题是专注于不改变原始数组,而是返回一个全新的数组。您可能想知道,为什么这种行为很重要?

一般来说,不修改数据有很多优点,这四种新的数组方法就证明了这一点。这些好处不仅限于数组,而是扩展到所有 JavaScript 对象。

尽管有很多好处,但下面概述了一些最重要的好处:

  • 纯函数:在函数式编程中,纯函数是在给定相同输入时始终产生相同输出的函数:它们没有任何副作用,并且它们的行为是可预测的。当你不修改数据时,使用这个函数式心智模型是理想的选择,这四种新的数组方法是一个很好的补充。
  • 可预测的状态管理:创建状态对象(或数组)的新副本通过消除意外更改并使用新副本表示特定时间点的数据,使状态管理更具可预测性。这简化了大规模状态管理,并总体上改进了有关状态管理的推理
  • 更改检测:像 React 这样的框架通过比较状态或 props 对象的两个副本来识别任何更改并相应地呈现用户界面,从而使用简化的更改检测。使用这些方法检测变化变得更加简单,因为我们可以在任何给定时刻比较两个对象以识别任何变化。

方法toReversed()

该方法与经典方法相似,但有明显的区别。 反转数组中的元素,而不改变原始数组。toReversed()reverse()toReversed()

考虑以下水果阵列:

const fruits = ["apple", "orange", "banana"]

现在,反向与:fruits.reverse()

// Reverse the array 
const result = fruits.reverse()
console.log(result) 

// ['banana', 'orange', 'apple']

console.log(fruits)
// ['banana', 'orange', 'apple']
//  original array is mutated

使用 ,原始数组发生突变。reverse()

要反转数组而不改变它,我们可以使用如下所示的方法:toReversed()

// Reverse the array 
const result = fruits.toReversed()
console.log(result) 

// ['banana', 'orange', 'apple']

console.log(fruits)
// ["apple", "orange", "banana"] 
//  original array is preserved

瞧!

如果您使用的是最新版本的当前浏览器(如 Chrome),则可以访问浏览器控制台并测试本文中提供的代码示例:

在浏览器控制台中尝试该方法toReversed

稀疏数组的行为

为了快速复习,稀疏数组是没有顺序元素的数组。例如,请考虑以下事项:

const numbers = [1,2,3]
// Assign an item to index 11
numbers[11] = 12

console.log(numbers)
// [1, 2, 3, empty × 8, 12]

在上面的示例中, 有八个空项目槽。 是一个稀疏数组。现在,回到 。这如何与稀疏数组一起工作?numbersnumberstoReversed()

toReversed()从不返回稀疏数组。如果原始阵列有空插槽,则它们将返回为 。undefined

考虑调用下面的数组:toReversed()numbers

const numbers = [1,2,3]
// Assign an item to index 11
numbers[11] = 12

numbers.toReversed()
// [12, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 3, 2, 1]

正如预期的那样,所有空插槽都作为数组项值返回。undefined



类数组对象的行为

即使专门存在于原型上,它也可以在类似数组的对象上调用。toReversed()Array

类似数组的对象通常具有属性和(可选)具有整数索引名称的属性。字符串对象是类数组对象的一个示例。length

该函数首先读取调用它的对象的属性,然后从末尾到开头遍历对象的整数键,这意味着从 to .它将每个属性的值添加到新数组的末尾,然后返回该数组。toReversed()lengthlength - 10

让我们试一试。考虑在字符串上的错误应用:toReversed()

const s = "Ohans Emmanuel"

// call `toReversed` directly on the string
s.toReversed()

//Uncaught TypeError: s.toReversed is not a function

即使字符串对象是一个类似数组的对象,这个程序也是错误的:我们不能以这种方式调用它,因为原型上不存在。string.toReversed()toReversedstring

但是,我们可能会使用如下所示的方法:call()

const s = "Ohans Emmanuel"

// Array.prototype.toReversed.call(arrayLike)
Array.prototype.toReversed.call(s)

//['l', 'e', 'u', 'n', 'a', 'm', 'm', 'E', ' ', 's', 'n', 'a', 'h', 'O']

一个自我构造的、类似数组的对象怎么样?请考虑以下示例:

// Has a length property and integer index property.
const arrayLike = {
 length: 5,
 2: "Item #2"
}

如果这是一个标准数组,它将是一个稀疏数组,即长度为五,第二个索引中的值。

考虑调用此内容的结果:toReversed

console.log(Array.prototype.toReversed.call(arrayLike))

// [undefined, undefined, 'Item #2', undefined, undefined]

该函数生成一个反向数组,而不创建稀疏数组。正如预期的那样,空插槽返回为 。toReversed()undefined

方法toSorted()

.toSorted()是经典方法的对应物。.sort()

您可能已经猜到了,与 不同,不会改变原始数组。考虑以下基本排序操作:.sort().toSorted().sort()

const list = [1, 5, 6, 3, 7, 8, 3, 7]
//Sort in ascending order 
const result = list.sort()

console.log(result)
// [1, 3, 3, 5, 6, 7, 7, 8]
console.log(list)
// [1, 3, 3, 5, 6, 7, 7, 8]

如上所示,对数组进行就地排序,从而改变数组。现在,考虑与以下相同的情况:sort()toSorted()

const list = [1, 5, 6, 3, 7, 8, 3, 7]
// Sort in ascending order 
const result = list.toSorted()

console.log(result)
// [1, 3, 3, 5, 6, 7, 7, 8]
console.log(list)
// [1, 5, 6, 3, 7, 8, 3, 7]

如上所示,返回一个元素排序的新数组。toSorted()



请注意,保留与 相同的语法。例如,我们可以指定一个定义排序顺序的函数,例如。toSorted()sort()list.toSorted(compareFn)

请考虑以下示例:

const list = [1, 5, 6, 3, 7, 8, 3, 7]
//Sort the array in descending order 
list.toSorted((a,b) => a < b ? 1 : -1)
// [8, 7, 7, 6, 5, 3, 3, 1]

稀疏数组的行为

空插槽将始终返回为 。事实上,它们被视为值为 .但是,不会为这些插槽调用 ,它们将始终位于返回数组的末尾。undefinedundefinedcompareFn

考虑以下示例,其中包含第一个插槽为空的数组:

// Note the empty initial slot 
const fruits = [, "apple", "orange", "banana"]

console.log(fruits.toSorted())

// ['orange', 'banana', 'apple', undefined]

此行为与初始值为 .请考虑以下示例:undefined

const fruits = [undefined, "apple", "orange", "banana"]

console.log(fruits.toSorted())

// ['orange', 'banana', 'apple', undefined]

另外,请注意,空插槽(或插槽)将始终移动到返回数组的末尾,无论它们在原始数组中的位置如何。undefined

请考虑以下示例:

// empty slot is in index 2
const fruits = ["apple", "orange", , "banana"]

console.log(fruits.toSorted())

// returned last 
// ['orange', 'banana', 'apple', undefined]

// undefined value is in index 2

const otherFruits = ["apple", "orange", undefined , "banana"]

console.log(otherFruits.toSorted())

// returned last 
// ['orange', 'banana', 'apple', undefined]

类数组对象的行为

当函数与对象一起使用时,它将首先读取对象的属性。然后,它将从头到尾收集对象的整数键,即从 to .对它们进行排序后,它将在新数组中返回相应的值。toSorted()lengththis0length - 1

请考虑以下带有字符串的示例:

const s = "Ohans Emmanuel"

// Array.prototype.toSorted.call(arrayLike)
Array.prototype.toSorted.call(s)
(14) [' ', 'E', 'O', 'a', 'a', 'e', 'h', 'l', 'm', 'm', 'n', 'n', 's', 'u']

请考虑以下示例,其中包含一个构造的类似数组的对象:

// Has a length property and integer index property.
const arrayLike = {
 length: 5,
 2: "Item #2"
10: "Out of bound Item" // This will be ignored since the length is 5
}

console.log(Array.prototype.toSorted.call(arrayLike))
// ['Item #2', undefined, undefined, undefined, undefined]

方法toSpliced(start,deleteCount,...items)

.toSpliced()是经典方法的对应物。与我们介绍的其他新方法一样,与 ..splice()toSpliced().splice()

的语法与 相同,如下所示:toSpliced.splice

toSpliced(start)
toSpliced(start, deleteCount)
toSpliced(start, deleteCount, item1)
toSpliced(start, deleteCount, item1, item2, itemN)

使用经典 添加新的数组项,如下所示:.splice()

const months = ["Feb", "Mar", "Apr", "May"] 
// Insert item "Jan" at index 0 and delete 0 items
months.splice(0, 0, "Jan")

console.log(months) 
//  ['Jan', 'Feb', 'Mar', 'Apr', 'May']

splice()插入新的数组项并改变原始数组。要在不改变原始数组的情况下创建新数组,请使用 。toSpliced()

考虑将上面的示例重写为使用 :toSpliced()

const months = ["Feb", "Mar", "Apr", "May"] 
// Insert item "Jan" at index 0 and delete 0 items
const updatedMonths = months.toSpliced(0, 0, "Jan")

console.log(updatedMonths)
// ['Jan', 'Feb', 'Mar', 'Apr', 'May']
console.log(months)
// ['Feb', 'Mar', 'Apr', 'May']

toSpliced()返回一个新数组而不改变原始数组。请注意两者的语法如何相同。toSpliced()splice()

稀疏数组的行为

toSpliced()从不返回稀疏数组。因此,空插槽将返回为 .undefined

请考虑以下示例:

const arr = ["Mon", , "Wed", "Thur", , "Sat"];
// Start at index 1, and delete 2 items
console.log(arr.toSpliced(1, 2)); 

// ['Mon', 'Thur', undefined, 'Sat']

类数组对象的行为

对于类似数组的对象,获取对象的长度,读取所需的整数键,并将结果写入新数组:toSplicedthis

const s = "Ohans Emmanuel"

// Start at index 0, delete 1 item, insert the other items
console.log(Array.prototype.toSpliced.call(s, 0, 1, 2, 3));

// [2, 3, 'h', 'a', 'n', 's', ' ', 'E', 'm', 'm', 'a', 'n', 'u', 'e', 'l']

方法with(index,value)

数组方法特别有趣。首先,考虑用于更改特定数组索引值的括号表示法:.with()

const favorites = ["Dogs", "Cats"]
favorites[0] = "Lions"

console.log(favorites)
//(2) ['Lions', 'Cats']

使用括号表示法,原始数组总是改变的。 实现在特定索引中插入元素的相同结果,但不会改变数组。相反,它会返回一个带有替换索引的新数组。.with()

让我们重写初始示例以使用:.with()

const favorites = ["Dogs", "Cats"]
const result = favorites.with(0, "Lions")

console.log(result)
// ['Lions', 'Cats']
console.log(favorites)
// ["Dogs", "Cats"]

稀疏数组的行为

with()从不返回稀疏数组。因此,空插槽将返回为:undefined

const arr = ["Mon", , "Wed", "Thur", , "Sat"];
arr.with(0, 2)
// [2, undefined, 'Wed', 'Thur', undefined, 'Sat']

类数组对象的行为

与其他方法类似,读取对象的属性。然后,它读取对象的每个正整数索引(小于 )。访问这些时,它会将其属性值保存到返回数组索引中。with()lengththislength

最后,在返回的数组上设置调用签名中的 and。请考虑以下示例:indexvaluewith(index, value)

const s = "Ohans Emmanuel"

// Set the value of the first item
console.log(Array.prototype.with.call(s, 0, "F"));

// ['F', 'h', 'a', 'n', 's', ' ', 'E', 'm', 'm', 'a', 'n', 'u', 'e', 'l']

结论

ECMAScript 标准在不断改进,利用它的新功能是个好主意。继续利用 、、 并创建更具声明性的 JavaScript 应用程序。toReversedtoSortedtoSplicedwith

最近发表
标签列表