首页 > 其他分享 >UES-10-增强数组

UES-10-增强数组

时间:2024-06-08 14:10:48浏览次数:22  
标签:10 元素 索引 参数 数组 缓冲区 类型化 UES

创建数组

Array.of() 方法将接收的每个参数作为数组元素创建并返回数组。和 Array 构造器相比,用于函数参数更可靠。

function create(fun, value) {
  return fun(value);
}

let items = create(Array.of, value);

Array.of 创建数组使用的是当前 of() 方法中的 this,而不是 Symbol.species 中返回的函数。

Array.from() 方法接收的第一个参数为类数组或可迭代对象时,会返回一个数组,数组中元素的值和顺序由参数中的项(元素)决定。这个方法创建数组时也没有使用 Symbol.species 属性返回的函数。

Array.from() 方法除了接收第一个参数外,第二个参数类型为函数,最终返回的数组元素是由第一个参数提供的元素经过作为第二个参数的函数处理之后得到的。

let arr = Array.from(arrayLike, e => e + 1);

如果 Array.from() 方法的作为第二个参数的函数中使用了某个对象的非方法属性,则需要将对应的对象作为第三个参数。

let obj = {
  value : 1,

  incre(v) {
    return v + this.value;
  }
};
// 用到了 obj 的属性 value
let arr = Array.from(arrayLike, obj.incre, obj);

新方法

find()findIndex() 方法的第一个参数为回调函数,第二个参数可选,表示回调函数中的 this 值。回调函数有三个参数,第一个表示值,第二个表示索引,第三个表示数组本身。遍历数组,如果某个元素满足回调函数中的条件时,find() 返回这个元素,findIndex() 返回这个元素的索引。

let arr = [9,8,7,6,3,2,1];
arr.find(e => e < 5);      // 3
arr.findIndex(e => e < 5); // 4

fill() 方法使用特定的值填充数组。有三个参数,其中后两个可选。第一个参数表示用于填充数组的值,第二个参数表示填充的起始索引,从该索引开始填充;第三个参数表示填充终止的索引,从该索引开始不再填充。不指定索引时,填充整个数组,即使数组有值,会用第一个参数的值覆盖已存在的值。如果后两个参数的值为负数,则实际索引值为数组长度加上传入的值。

copyWithin() 方法用于选择数组中部分连续的元素替换数组中部分连续的元素。该方法有三个参数,第一个参数表示该索引开始的元素将被替换,第二个参数表示该索引开始的元素将被用于替换其他元素,第三个参数可选,表示用于替换的元素索引到此结束,不包含该索引。如果表示索引的参数为负数,则处理方式与 fill() 一致。

let arr = [1,2,3,4];
arr.copyWithin(2, 0, 1); // [1,2,1,4]

类型化数组

类型化数组是用来存储和处理不同数值类型的元素,为了节省内存。

无论是整数还是浮点数,js 都使用 64 位进行存储,造成了内存的浪费。类型化数组存储和处理的数据类型有 int8/uint8/int16/uint16/int32/uint32/int64/uint64 合计 8 种,每一种占用的内存空间由名称可知。

数组缓冲区(array buffer)类似于 C 语言中 malloc 分配的内存,表示一段连续的内存。创建数组缓冲区时,传入构造器的参数表示分配以字节为单位的内存大小。数组缓冲区一旦创建完成,则不能更改大小。byteLength 属性存储了分配的内存字节数。可以在一个已创建的数组缓冲区上使用 slice() 方法创建新的和已有数组缓冲区共享内存的数组缓冲区。

let ab = new ArrayBuffer(6);
ab.byteLength; // 6
let another = ab.slice(2, 5); // 将 ab 的第 2 到 4 个字节作为新的数组缓冲区

视图提供了处理数组缓冲区的接口。DataView 类型是所有数组缓冲区通用的视图。创建 DataView 时需要向构造器传入一个数组缓冲区表示与该数组缓冲区关联。构造器有三个参数,后两个可选。第一个参数为与视图关联的数组缓冲区,第二个参数为视图允许在数组缓冲区上处理的起始位置,以字节为单位距离数组缓冲区起始地址的偏移量;第三个参数为视图允许在数组缓冲区上处理的范围,以字节为单位。

let ab = new ArrayBuffer(8);
let dv = new DataView(ab);
new DataView(ab, 2, 5); // 允许处理的范围为从第 2 个字节开始连续的 5 个字节

视图有 3 个只读属性:buffer 存储和该视图绑定的数组缓冲区。byteOffset 存储创建视图时传入的第二个参数,也就是距离数组缓冲区首地址的偏移量,创建时没有传参则默认为 0。byteLength 存储创建视图时传入的第三个参数,即视图可处理的范围大小,创建时没有传参则默认为数组缓冲区的 byteLength 属性。

视图提供了 getIntX()getUnitX()setIntX()setUnitX()getFloatY()setFloatY() 方法读写数据。其中 X 可替换成 8/16/32/64,Y 可替换成 32/64,对应不同的位数。get 有两个参数,第一个参数为从距离视图可处理范围的起始位置的偏移量,从该处读取数据,读取的位数由方法名中的数字决定;第二个参数可选,默认为 false,表示数据是否以低字节优先的方式存储。set 有三个参数,第一个参数和 get 方法一致,表示偏移量,第二个参数表示要写入到该偏移量位置的值,第三个参数可选,与 get 的第二个参数含义一致。低字节优先表示存储一个数时,先将该数的二进制表示的高位存储到低字节位置,然后次高位存储到次低字节位置,按这种方式存储。这些方法读写数据时,根据方法名中的位数读写,这些位存储的数据不影响方法的使用。

let ab = ArrayBuffer(8);
let dv = DataView(ab);
dv.setInt8(0, 100);
dv.getInt8(0); // 100

类型化数组实际上是特定类型视图对数组缓冲区的绑定。类型有 IntXArray、UintXArray、FloatYArray、Uint8ClampedArray。其中 X 可替换成 8/16/32/64,Y 可替换成 32/64,数字表示了该类型可处理的位数。其中 Uint8ClampedArray 和 Unit8Array 的区别为,当数组缓冲区内值溢出时,Uint8ClampedArray 会将其转换成 0(如果值小于 0) 或者 255(如果值大于 255)。

每种类型都有一个 BYTES_PER_ELEMENT 属性表示每种类型可处理的数据所占用的字节数。

创建特定类型视图的第一种方式与创建 DataView 方法一致,同时也具有 DataView 的三个只读属性。

第二种方式是传递单个参数给类型化数组构造器,表示创建的数组允许存储的元素个数。length 属性保存了这个数。如果传递的参数为 0,表示类型化数组没有分配空间,不能存储数据。

let i = new Int8Array(10);
i.length;     // 10
i.byteLength; // 10

第三种方式是传递单个对象给类型化数组构造器。允许传递的对象有类型化数组、可迭代对象、数组、类对象数组。传递这些对象时,分别:使用类型化数组的元素初始化新类型化数组、使用可迭代对象元素初始化新类型化数组,如果元素不匹配,抛出错误、使用数组元素初始化新类型化数组,元素不匹配则抛出错误、与传入对象为数组时初始化过程一致。

类型化与常规数组相似点

类型化数组的 length 属性与常规数组一样,表示元素个数,只不过是只读的,不能修改该属性值。类型化数组也是通过数值索引访问元素。

类型化数组有 copyWithin()entries()fill()filter()find()findIndex()forEach()indexOf()join()keys()lastIndexOf()map()reduce()reduceRight()reverse()slice()some()sort()values() 方法,其中有返回值的方法,返回值的类型是类型化数组。

类型化数组也有三个迭代器 entries()keys()values(),使用扩展运算符可以将其转换成常规数组。

let int8s = new Int8Array([1,2]);
let ints = [...int8s];
ints instanceof Array; // true

类型化数组的 of()from() 方法与常规数组的一样,除了返回类型是类型化数组。

类型化与常规数组区别

类型化数组创建之后长度保持不变,如果使用不在有效索引范围内的索引时,会忽略该操作。如果向类型化数组中添加无效值或者修改某元素为无效值时,会将无效值转换成 0 再进行处理。

类型化数组没有的方法:concat()pop()push()shift()splice()unshift()

类型化数组特有的两个方法:set()subarray()set() 方法有两个参数,第一个参数接收任意类型的数组(无论是常规还是类型化),第二个参数为偏移量,表示从该索引开始将第一个参数的所有元素复制到数组中。subarray() 方法的两个参数都是可选的,第一个参数表示起始索引,第二个参数表示终止索引,将起始索引到终止索引前的一个索引范围内的元素作为一个新的类型化数组的元素,然后创建并返回这个新的类型化数组。

参考

[1] Zakas, Understanding ECMAScript 6, 2017.

标签:10,元素,索引,参数,数组,缓冲区,类型化,UES
From: https://www.cnblogs.com/xdreamc/p/16556217.html

相关文章

  • 华为OD刷题C卷 - 每日刷题 8(整形数组按个位值排序,停车场车辆统计)
    两段代码分别解决了两个不同的算法问题,下面是对它们的概述:1、(整形数组按个位值排序):这段代码是解决“整形数组按个位值排序”的问题。它提供了一个Java类Main,其中包含main方法,用于读取输入、执行排序并打印结果。代码首先使用Scanner从标准输入读取一行文本,该文本包含一个......
  • P10466 邻值查找 题解
    题目传送门前置知识二叉搜索树&平衡树解法笔者写这篇题解的时候题面应该是出锅了,建议去看Acwing的题面。第一问同luoguP2234[HNOI2002]营业额统计,平衡树维护前驱、后继(非严格意义上的)求出差值后取\(\min\)即可;第二问用map实现一个映射即可维护位置。代码#incl......
  • P10499 开关问题 题解
    题目传送门前置知识高斯消元法解异或方程组|乘法原理解法把开关的相互影响关系转化成异或,然后就转化成了异或方程组,高斯消元求解即可。判断是否存在解的过程同luoguP2455[SDOI2006]线性方程组。由于自由元仅能取\(0/1\),故总方案数为\(2\)的自由元数量次方。代码......
  • 【Java笔记】第10章:接口
    前言1.接口的概念与定义2.接口的声明与语法3.接口的实现4.接口的继承5.接口的默认方法6.接口的静态方法7.接口的私有方法8.接口的作用9.接口与抽象类的区别10.接口在Java集合中的应用结语上期回顾:【Java笔记】第9章:三个修饰符个人主页:C_GUIQU归属专......
  • 掌握Python 这10个OOP技术,代码想写不好都难!
    目录1、面向对象设计原则......
  • Python面试宝典:Python中与设计模式相关的面试笔试题(1000加面试笔试题助你轻松捕获大厂
    Python面试宝典:1000加python面试题助你轻松捕获大厂Offer【第二部分:Python高级特性:第二十二章:代码设计和设计模式:第二节:设计模式】第二十二章:代码设计和设计模式第二节:设计模式创建型模式结构型模式行为型模式python中与设计模式相关的面试笔试题面试题1面试......
  • Python面试宝典:Python中与数据处理与清洗相关的面试笔试题(1000加面试笔试题助你轻松捕
    Python面试宝典:1000加python面试题助你轻松捕获大厂Offer【第二部分:Python高级特性:第二十六章:Python与数据科学:第二节:数据处理与清洗】第二十六章:Python与数据科学第二节:数据处理与清洗1.数据处理工具1.1Pandas1.2NumPy2.数据清洗工具2.1处理缺失......
  • docker拉取镜像报错Bad Request
    问题现象docker拉取镜像报错BadRequest。问题分析cat/etc/systemd/system/docker.service.d/http-proxy.conf1.1.1.1:80模拟错误的docker代理配置,错误的代理导致镜像拉取失败。解决问题注释代理配置。vim/etc/systemd/system/docker.service.d/http-proxy.conf重启d......
  • [leetcode 30 串联所有单词的子串 10ms]
    算法复杂度o(1):复杂最坏复杂度是o(s.length)和o(m*total)的最大值码代码速度要变快,变量,算法要先想清楚importjava.util.*;classSolution{publicList<Integer>findSubstring(Strings,String[]words){m=words[0].length();n=words......
  • P10560 [ICPC2024 Xi'an I] The Last Cumulonimbus Cloud 题解
    好好玩的题。思路对于一个图上邻域问题,我们有一个很经典的做法:根号分治。考虑根号分治的本质是什么。我们把点分成两类,平衡每一种点的时间,也就是度数大的与度数小的点。所以对于这道题,我们有了更加好的做法。发现题目给的图的性质就是一个天然的划分方案。我们每次找到图中......