JS即将发布数组的4个新特性,真香!

const odd = { odd: true };

const even = { even: true };

array.groupByToMap((num, index, array) => {

return num % 2 === 0 ? even: odd;

});

// => Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

如果没有groupByToMap提案,我们过去是这么实现:

Array.prototype.groupByToMap = function(callback) {

const mapObject = new Map();

for(let i =0; i < this.length; i++) {

let key = callback(this[i],i,this);

if(mapObject.get(key)) {

mapObject.get(key).push(this[i])

} else {

mapObject.set(key,[this[i]])

}

}

return mapObject;

}

评价:实际开发中,类似这样的数组 [ 1 , 2 , 3 , 4 , 5 ],如果要分奇数偶数的话,需要重新声明一个对象来存储。

const obj = { odd: [1, 3, 5], even: [2, 4] }

groupBy提案返回的是一个null-prototype对象,{ odd: [1, 3, 5], even: [2, 4] },不需要再声明一个具名对象。groupByToMap返回的是一个常规Map对象,总体来说比较实用。

提案三 Array find from last

从数组的最后一个到第一个查找元素的方法

使用案例:

按照以前的js写法,要想倒叙查询数组元素。

先进行一次反转reverse,反转一次数组,再使用find进行查询。

const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];

[…array].reverse().find(n => n.value % 2 === 1);

// { value: 3 }

或者在原型上挂一个方法来实现:

Array.prototype.findLast = function(callback) {

const len = this.length;

for(let i = len - 1; i > 0; i–) {

if(callback(this[i],i,this)) {

return this[i]

}

}

return -1

}

Array find from last 提案方案:

通过提案提供的方法findLast,支持了直接逆向查询数组。

array.findLast(n => n.value % 2 === 1); // { value: 3 }

评价:从性能看,减少了一次数组反转,确实有看的见的优化。从语义上来说,有正向查询就应该有反向查询,符合人们的思维习惯,总体来说比较实用。

提案四   Resizable and growable Array Buffer

扩展ArrayBuffer构造函数,采用额外的最大长度,以允许就地增长和缩小缓冲区。

在介绍提案之前,需要提前了解下什么是ArrayBuffer,它是解决什么问题的,怎么用,在哪里用。这样会方便理解该提案。以下介绍ArrayBuffer的内容我已经过滤了很多细枝末节的理论,希望能做到之前没有这方面基础的同学也可以一次性读懂ArrayBuffer

Array Buffer这个概念,大家在日常开发中几乎不会直接接触这个概念,但和我们关系却很密切。

简单理解Array Buffer,可以说它让ECMAScript操作内存空间成为可能。它的诞生是因为一个项目,WebGL,这个项目里需要浏览器与显卡进行频繁的通信,而以往的文本传输,需要把文本’hello wrold’,翻译01010111…类似这样的机器语言,非常消耗性能,而直接以二进制的形式通信就非常有必要了,Array Buffer也就此诞生;

const buffer = new ArrayBuffer(32);

这样创建了一段32字节的内存空间,buffer。有一些约定好的特性,比如生成的ArrayBuffer,不能被直接修改,需要通过 TypedArray视图和DataView视图修改,TypedArray就是一系列更改内存的构造函数统称,比如Uint8ArrayUint16ArrayUint32Array,DataView是更灵活的操作ArrayBuffer的视图。大概是因为最开始设计是为了解决图像绘制的问题,所以就起名叫各种视图,记住就ok了。

以下是TypedArray视图支持的一些数据类型

| 数据类型 | 字节长度 | 含义 | 对应的 C 语言类型 |

| — | — | — | — |

| Int8 | 1 | 8 位带符号整数 | signed char |

| Int16 | 2 | 16 位带符号整数 | short |

| Int32 | 4 | 32 位带符号整数 | int |

//生成12字节的内存空间

const buffer = new ArrayBuffer(12);

//用Int32Array视图读取这个内存空间

const x1 = new Int32Array(buffer);

//直接修改

x1[0] = 1;//1

//用Int8Array视图读取这个内存空间

const x2 = new Uint8Array(buffer);

x2[0] = 2;//2

//x1的值发生变化

x1[0] // 2

上面代码对同一段内存,分别建立两种视图:32 位带符号整数(Int32Array构造函数)和 8 位不带符号整数(Uint8Array构造函数)。由于两个视图对应的是同一段内存,一个视图修改底层内存,会影响到另一个视图。

ArrayBuffer 的一些理解

Array Buffer是一个二进制数组,也可以说是一个构造函数,但本质上是一个由一堆 0 1 组成的缓存空间,他在内存中主要发挥数据缓冲的作用。简单理解就是计算机要运行,就是cpu要处理 0 1 组成的二进制数据,但有时二进制数据来的又快又多,cpu还在处理其他任务,那这些数据就得原地等待,如果cpu处理任务很快,但是数据传输的慢了,就得让cpu空闲等待数据,造成资源浪费,ArrayBuffer就是充当一个缓冲内存空间。让这个内存空间随时数据存在,不会让数据和cpu等待。

ArrayBuffer 遇到的瓶颈

现有的ArrayBuffer存在一个问题,当你正在的ArrayBuffer空间不够需要增加空间时,需要调用ArrayBuffer原型上的一个方法,ArrayBuffer.prototype.slice(),使用如下

const buffer = new ArrayBuffer(8);

const newBuffer = buffer.slice(0, 3);

上面代码拷贝buffer对象的前 3 个字节(从 0 开始,到第 3 个字节前面结束),生成一个新的ArrayBuffer对象。

slice方法其实包含两步,第一步是先分配一段新内存,第二步是将原来那个ArrayBuffer对象拷贝过去。

这样的方式一次使用尚且可以,但在一些绘图场景下,频繁地创建新内存,再复制一份过去,会大量损耗性能。

改造 ArrayBuffer

以上就介绍完了ArrayBuffer,和它目前面临的瓶颈。下面讲一下本次进入stage3的提案。

本提案拓展了ArrayBuffer的构造函数,增加最大和最小伸缩长度的配置—maximumByteLength。重写了transfer方法,可以用来直接转移内存空间,不必再复制一份内存再挪动。

改造之后的ArrayBuffer构造函数

class ArrayBuffer {

//options为配置项

//maximumByteLength 配置内存伸缩长度

constructor(byteLength,[ options ]);

//挪动内存

transfer(newByteLength);

//更改内存长度

resize(newByteLength);

//分离出一个不可调整大小的ArrayBuffer

slice(start, end);

//判断是否可以伸缩

resizable();

//获取配置的最大内存长度

maximumByteLength();

//获取当前内存长度

byteLength();

}

使用案例:

声明一个1024字节的内存,并把最大内存长度设置为1024的平方

//增加配置项,maximumByteLength,最大内存长度允许到1024的平方

let rab = new ArrayBuffer(1024, { maximumByteLength: 1024 ** 2 });

//当前内存长度 1024字节

assert(rab.byteLength === 1024);

//最大长度 1024平方字节

assert(rab.maximumByteLength === 1024 ** 2);

//可以就地更改长度

assert(rab.resizable);

//更改内存长度

rab.resize(rab.byteLength * 2);

//内存长度发生变化

assert(rab.byteLength === 1024 * 2);

transfer是对内存进行挪动

let ab = rab.transfer(1024);

上面是挪动从0开始的1024字节

assert(rab.byteLength === 0);

assert(rab.maximumByteLength === 0);

上面是原来的内存(rab)被分离,并清除内存。

// 内存被转移到ab

assert(!ab.resizable);

assert(ab.byteLength === 1024);

内存成功被转移到ab

SharedArrayBuffer

SharedArrayBuffer 顾名思义就是可以共享的ArrayBuffer

ArrayBuffer提案里,将SharedArrayBuffer也进行了改动,让他支持可以增长内存。

先简单介绍下什么是SharedArrayBuffer

在ECMAScript里有一些计算任务通常会让在worker线程里,每个worker线程都是互相隔离的,他们之间的通信需要通过postMessage来完成。

除了可以进行字符串数外,也可以进行二进制数据通信,但需要将二进制数据复制一份再用过postMessage传递给另一个线程,数据量很大时效率会变低,所以在 es2017 时有人提出了可以共享的SharedArrayBuffer,js的主线程和worker线程可以共享这块内存空间,同时进行数据读写,避免了复制二进制数据带来的性能损耗。

实际场景里,在主线程创建了一个SharedArrayBuffer,并把内存地址通过postMessage发给worker线程

// 主线程

// 新建 1KB 共享内存

const sharedBuffer = new SharedArrayBuffer(1024);

// 主线程将共享内存的地址发送出去

w.postMessage(sharedBuffer);

worker线程接受来自主线程的共享地址 ---- SharedArrayBuffer,不必再复制同一份二进制地址进行传递。通过共享地址提高了性能。

// Worker 线程

onmessage = function (ev) {

// 主线程共享的数据,就是 1KB 的共享内存

const sharedBuffer = ev.data;

// 在共享内存上建立视图,方便读写

const sharedArray = new Int32Array(sharedBuffer);

// …

};

ArrayBuffer提案对SharedArrayBuffer也进行了拓展,允许SharedArrayBuffer支持增加内存,但与ArrayBuffer不同的是,不支持减少内存,很显然,如果减少内存的话,很有可能影响到正在共享这块内存的其他程序。

下面是SharedArrayBuffer的构造函数。在ArrayBuffer构造函数里的resize,这里命名是grow,也能体现出两者的差异了。

class SharedArrayBuffer {

//和ArrayBuffer一样配置maximumByteLength

constructor(byteLength, [ options ]);

//只能增加内存,而不能缩短内存

grow(newByteLength);

//分离出一份不可增长的 SharedArrayBuffer。

slice(start, end);

//判断是否可以扩充内存

growable();

//获取最大内存长度

maximumByteLength();

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-sdGxYpaA-1715543877058)]

[外链图片转存中…(img-nRaVLJFj-1715543877059)]

[外链图片转存中…(img-ixArSEtG-1715543877059)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值