大家好,我是 CUGGZ。
ECMAScript 规范每年都会更新一次,正式标准化 JavaScript 语言的 ECMAScript 的下一次年度更新将在 2023 年 6 月左右获得批准,这将是 ECMAScript 的第 14 版。所有在 2023 年 3 月之前达到阶段 4 的提案都将包含在 ECMAScript 2023 标准中。 对于一个提案,从提出到最后被纳入 ECMAScript 标准,总共分为五步:
根据 Erick Wendel(微软 MVP、谷歌开发专家、@nodejs合作者)的预测,ECMAScript 2023 可能会新增以下数组方法(3️⃣、4️⃣为所处提案阶段):
下面就来看看这些方法是如何使用的吧!
通过副本更改数组的提案目前处于第 3 阶段。该提案为数组和类型化数组提出了四种新的方法:
提案地址:https://github.com/tc39/proposal-change-array-by-copy
为什么会有这个提案呢?我们知道,大多数的数组方法都是非破坏性的,也就是说,在数组执行该方法时,不会改变原数组,比如 filter() 方法:
const arr = ['a', 'b', 'b', 'a'];
const result = arr.filter(x => x !== 'b');
console.log(result); // ['a', 'a']
当然,也有一些是破坏性的方法,它们在执行时会改变原数组,比如 sort() 方法:
const arr = ['c', 'a', 'b'];
const result = arr.sort();
console.log(result); // ['a', 'b', 'c']
在数组的方法中,下面的方法是具有破坏性的:
如果我们想要这些数组方法应用于数组而不改变它,可以使用下面任意一种形式:
const sorted1 = arr.slice().sort();
const sorted2 = [...arr].sort();
const sorted3 = Array.from(arr).sort();
可以看到,我们首先需要创建数组的副本,再对这个副本进行修改。
因此改提案就引入了这三个方法的非破坏性版本,因此不需要手动创建副本再进行操作:
该提案将这些函数属性引入到 Array.prototype:
除此之外,该提案还还提出了一个新的非破坏性方法:with()。该方法会以非破坏性的方式替换给定 index 处的数组元素,即 arr[index]=value 的非破坏性版本。
所有这些方法都将保持目标数组不变,并返回它的副本并执行更改。这些方法适用于数组,也适用于类型化数组,即以下类的实例:
TypedArray是一种通用的固定长度缓冲区类型,允许读取缓冲区中的二进制数据。其在WEBGL规范中被引入用于解决Javascript处理二进制数据的问题。类型化数组也是数组,只不过其元素被设置为特定类型的值。
类型化数组的核心就是一个名为 ArrayBuffer 的类型。每个ArrayBuffer对象表示的只是内存中指定的字节数,但不会指定这些字节用于保存什么类型的数据。通过ArrayBuffer能做的就是为了将来使用而分配一定数量的字节。
这些提案也适用于元组,元组相当于不可变的数组。它们拥有数组的所有方法——除了破坏性的方法。因此,将后者的非破坏性版本添加到数组对元组是有帮助的,这意味着我们可以使用相同的方法来非破坏性地更改数组和元组。
(1)Array.prototype.toReversed()
toReversed() 是 reverse() 方法的非破坏性版本:
const arr = ['a', 'b', 'c'];
const result = arr.toReversed();
console.log(result); // ['c', 'b', 'a']
console.log(arr); // ['a', 'b', 'c']
下面是 toReversed() 方法的一个简单的 polyfill:
if (!Array.prototype.toReversed) {
Array.prototype.toReversed = function () {
return this.slice().reverse();
};
}
(2)Array.prototype.toSorted()
toSorted() 是 sort() 方法的非破坏性版本:
const arr = ['c', 'a', 'b'];
const result = arr.toSorted();
console.log(result); // ['a', 'b', 'c']
console.log(arr); // ['c', 'a', 'b']
下面是 toSorted() 方法的一个简单的 polyfill:
if (!Array.prototype.toSorted) {
Array.prototype.toSorted = function (compareFn) {
return this.slice().sort(compareFn);
};
}
(3)Array.prototype.toSpliced()
splice() 方法比其他几种方法都复杂,其使用形式:splice(start, deleteCount, ...items)。该方法会从从 start 索引处开始删除 deleteCount个元素,然后在 start 索引处开始插入item 中的元素,最后返回已经删除的元素。
toSpliced 是 splice() 方法的非破坏性版本,它会返回更新后的数组,原数组不会变化,并且我们无法再得到已经删除的元素:
const arr = ['a', 'b', 'c', 'd'];
const result = arr.toSpliced(1, 2, 'X');
console.log(result); // ['a', 'X', 'd']
console.log(arr); // ['a', 'b', 'c', 'd']
下面是 toSpliced() 方法的一个简单的 polyfill:
if (!Array.prototype.toSpliced) {
Array.prototype.toSpliced = function (start, deleteCount, ...items) {
const copy = this.slice();
copy.splice(start, deleteCount, ...items);
return copy;
};
}
(4)Array.prototype.with()
with()方法的使用形式:with(index, value),它是 arr[index] = value 的非破坏性版本。
const arr = ['a', 'b', 'c'];
const result = arr.with(1, 'X');
console.log(result); // ['a', 'X', 'c']
console.log(arr); // ['a', 'b', 'c']
下面是 with() 方法的一个简单的 polyfill:
if (!Array.prototype.with) {
Array.prototype.with = function (index, value) {
const copy = this.slice();
copy[index] = value;
return copy;
};
}
(1)概述
在日常开发中,数组分组是一种极其常见的操作。因此,proposal-array-grouping 提案就提出了两个新的数组方法:
提案地址:https://github.com/tc39/proposal-array-grouping
下面是这两个方法的类型签名:
Array.prototype.group (
callback: (value: Elem, index: number, array: Array) => GroupKey,
thisArg?: any
): {[k: GroupKey]: Array}
Array.prototype.groupToMap (
callback: (value: Elem, index: number, array: Array) => GroupKey,
thisArg?: any
): Map>
这两个方法都用来对数组进行分组:
这两个方法都会对数组进行遍历,它们会向其回调请求组键并将元素添加到相应的组中。这两个方法在表示组的方式上有所不同:
那这两个方法该如何选择呢?我们知道,JavaScript 中对象是支持解构的,如果想要使用解构来获取数组中的值,比如,对于上面对象,可以通过解构获取三个不同组的值:
const {vegetables, fruit, meat} = result;
而 Map 的好处就是它的 key 不限于字符串和symbol,更加自由。
(2)使用
下面来看几个实用例子。假如执行 Promise.allSettled() 方法返回的数组如下:
const settled = [
{ status: 'rejected', reason: 'Jhon' },
{ status: 'fulfilled', value: 'Jane' },
{ status: 'fulfilled', value: 'John' },
{ status: 'rejected', reason: 'Jaen' },
{ status: 'rejected', reason: 'Jnoh' },
];
const {fulfilled, rejected} = settled.group(x => x.status);
// fulfilled 结果如下:
[
{ status: 'fulfilled', value: 'Jane' },
{ status: 'fulfilled', value: 'John' },
]
// rejected 结果如下:
[
{ status: 'rejected', reason: 'Jhon' },
{ status: 'rejected', reason: 'Jaen' },
{ status: 'rejected', reason: 'Jnoh' },
]
在这个例子中,使用 group() 的效果会更好,因为可以使用解构轻松获取需要组的值。
假如想要对以下数组中人根据国家进行分组:
const persons = [
{ name: 'Louise', country: 'France' },
{ name: 'Felix', country: 'Germany' },
{ name: 'Ava', country: 'USA' },
{ name: 'Léo', country: 'France' },
{ name: 'Oliver', country: 'USA' },
{ name: 'Leni', country: 'Germany' },
];
const result = persons.groupToMap((person) => person.country);
// result 的执行结果和以下 Map 是等价的:
new Map([
[
'France',
[
{ name: 'Louise', country: 'France' },
{ name: 'Léo', country: 'France' },
]
],
[
'Germany',
[
{ name: 'Felix', country: 'Germany' },
{ name: 'Leni', country: 'Germany' },
]
],
[
'USA',
[
{ name: 'Ava', country: 'USA' },
{ name: 'Oliver', country: 'USA' },
]
],
])
在这个例子中,groupToMap() 是更好的选择,因为哦嗯嗯可以在Map 中使用任何类型的键,而在对象中,键值只能是字符串或symbol。
(3)polyfill
下面来实现一下这两个方法:
Array.prototype.group = function (callback, thisArg) {
const result = Object.create(null);
for (const [index, elem] of this.entries()) {
const groupKey = callback.call(thisArg, elem, index, this);
if (! (groupKey in result)) {
result[groupKey] = [];
}
result[groupKey].push(elem);
}
return result;
};
Array.prototype.groupToMap = function (callback, thisArg) {
const result = new Map();
for (const [index, elem] of this.entries()) {
const groupKey = callback.call(thisArg, elem, index, this);
let group = result.get(groupKey);
if (group === undefined) {
group = [];
result.set(groupKey, group);
}
group.push(elem);
}
return result;
};
(1)概述
在 JavaScript 中,通过 find() 和 findIndex() 查找数组中的值是一种常见做法。不过,这些方法从数组的开始进行遍历:
const array = [{v: 1}, {v: 2}, {v: 3}, {v: 4}, {v: 5}];
array.find(elem => elem.v > 3); // {v: 4}
array.findIndex(elem => elem.v > 3); // 3
如果要从数组的末尾开始遍历,就必须反转数组并使用上述方法。这样做就需要一个额外的数组操作。幸运的是,Wenlu Wang 和 Daniel Rosenwasser 关于findLast() 和 findLastIndex() 的 ECMAScript 提案解决了这一问题。该提案的一个重要原因就是:语义。
提案地址:https://github.com/tc39/proposal-array-find-from-last
(2)使用
它们的用法和find()、findIndex()类似,唯一不同的是它们是 从后向前 遍历数组,这两个方法适用于数组和类数组。
findLast() 会返回第一个查找到的元素,如果没有找到,就会返回undefined;
findLastIndex() 会返回第一个查找到的元素的索引。如果没有找到,就会返回 -1;
const array = [{v: 1}, {v: 2}, {v: 3}, {v: 4}, {v: 5}];
array.findLast(elem => elem.v > 3); // {v: 5}
array.findLastIndex(elem => elem.v > 3); // 4
array.findLastIndex(elem => elem.v > 5); // undefined
(3)polyfill
下面来实现一下这两个方法:
Array.prototype.findLast = function(arr, callback, thisArg) {
for (let index = arr.length - 1; index >= 0; index--) {
const value = arr[index];
if (callback.call(thisArg, value, index, arr)) {
return value;
}
}
return undefined;
}
Array.prototype.findLastIndex = function(arr, callback, thisArg) {
for (let index = arr.length - 1; index >= 0; index--) {
const value = arr[index];
if (callback.call(thisArg, value, index, arr)) {
return index;
}
}
return -1;
}
(4)参考源码
lodash 中也提供了类似方法,下面是相关源码:
import findLastIndex from './findLastIndex.js'
import isArrayLike from './isArrayLike.js'
/**
* This method is like `find` except that it iterates over elements of
* `collection` from right to left.
*
* @since 2.0.0
* @category Collection
* @param {Array|Object} collection The collection to inspect.
* @param {Function} predicate The function invoked per iteration.
* @param {number} [fromIndex=collection.length-1] The index to search from.
* @returns {*} Returns the matched element, else `undefined`.
* @see find, findIndex, findKey, findLastIndex, findLastKey
* @example
*
* findLast([1, 2, 3, 4], n => n % 2 == 1)
* // => 3
*/
function findLast(collection, predicate, fromIndex) {
let iteratee
const iterable = Object(collection)
if (!isArrayLike(collection)) {
collection = Object.keys(collection)
iteratee = predicate
predicate = (key) => iteratee(iterable[key], key, iterable)
}
const index = findLastIndex(collection, predicate, fromIndex)
return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined
}
export default findLast
import baseFindIndex from './.internal/baseFindIndex.js'
import toInteger from './toInteger.js'
/**
* This method is like `findIndex` except that it iterates over elements
* of `collection` from right to left.
*
* @since 2.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} predicate The function invoked per iteration.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the found element, else `-1`.
* @see find, findIndex, findKey, findLast, findLastKey
* @example
*
* const users = [
* { 'user': 'barney', 'active': true },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': false }
* ]
*
* findLastIndex(users, ({ user }) => user == 'pebbles')
* // => 2
*/
function findLastIndex(array, predicate, fromIndex) {
const length = array == null ECMAScript2023将新增的九个数组方法
转载来于:http://www.shufengxianlan.com/qtweb/news1/440851.html网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联