引言
对于Javascript中的数组,大家可能会马上想到:
let arr = [46,456,465,798];
let arr2 = new Array()
arr2[0] = 46
arr2[1] = 456 ...
很方便的我们就创建了arr,arr2两个数组。在我们的印象中,对Array对象已经跟数组划分为同一个东西了,可其实它是一个从哈希表扩展的结构体,它提供了push`splice等一些操作,而它们的效率是很低的。在Javascript中可以创建真正的数组,那就是强类型数组。
在了解什么是强类型数组之前,我们先来看一道题目:
不使用loop循环,创建一个长度为100的数组,并且每个元素的值等于它的下标。
我们来分析:第一步,创建一个长度为100的数组,第二步,让每个元素的值等于它的下标,不能使用使用循环。写成代码就是:
let arr = new Array(100)
arr.map((item, index) => index)
console.log(arr)
是不是感觉很简单,那么我们马上去控制台看看输出了我们想要结果没有:
结果是空的,只有长度却没有内容,我们再在jsbin的console里面看看输出了什么:
有一个长度为100的,内容全都是undefined的数组,也就是说map方法并没有帮助我们获取到index。这是因为Javascript数组是稀疏数组,虽然长度是100,单实际上是一个空数组,里面没有真实存在的元素,所以使用map方法,是不会去遍历这个数组100次的,因此需要让这个数组有内容:
let arr = new Array(100).join(',').split(',')
我们先用join方法将这100个数组通过”,”逗号合并为一个字符串,然后再以”,”逗号为分割符把字符串分割为数组,就得到了一个长度为100的,“空”数组:
然后再通过.map方法来改变元素的值:
let arr = new Array(100).join(',').split(',')
let newArr = arr.map((item, index) => index)
console.log(newArr)
就得到了我们想要的结果:
让我们看一下最终代码做了些什么,先是创建一个数组,然后通过join方法把它转换成字符串,然后再通过split方法把字符串转换成数组,最后再通过map函数改变数组内的值。那么有没有一种创建出来直接就可以进行map方法的数组呢?答案是有的,那就是javascript的强类型数组。
“强类型数组”简介
概述
随着Javascript的发展,Javascript现在可以调用一些系统底层的东西乳WebGL,这些底层的操作需要直接访问内存,而Javascript本身的Array在内存中是分散无法与底层操作对接,因此引入了这些强类型的数组。
强类型数组有三种基本类型:
- Int 整数
- Uint 无符号整数
- Float IEEE754 浮点数
根据这些基本类型可以引申出8中类数组:
- Int8Array
- Uint8Array
- Ini16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
这些类数组的规律性很强,命名都是: 基本类型+位数+Array。我们都知道一个字节是8位的,所以8位的数组中每个元素就占一个字节。同理可知64位的数组每个元素占8个字节。就拿Int8Array来说,它是8位的整数。8位可以表示28=256个数字。而Int是有符号的,所以Int8Array的元素可以表示-128到127的整数。而Uint8Array的元素是无符号的,同理可知它可以表示0-255的整数。由于这些数组是使用线性储存,因此它们是定长的,无法给数组添加元素。超出索引的赋值不会报错,也不会生效。
使用
简单调用
通过new一个(基本类型)+(位数)+Array就可以得到一个我们想要的数组:
let a = new Uint8Array(5)
console.log(a)
在这里我们得到了长度为5的8位无符号整形的空数组:
我们还可以通过传递一个array对象来把它转换为强类型数组:
let arr = [1,2,3]
let a = new Uint8Array(arr)
console.log(a)
这样会得到一个跟Array对象相同数据的强类型数组:
这是最常用的两种创建方式。第一种传入数组大小,创建与传入值相同长度的数组,并且把数组内的元素都初始化为0。第二种传入Array对象进行转换,这样得到的数组每一项的值就是原来Array对象中每一项的值,而遇到无法转换的(如英文字符串等)则被置为0:
let a = new Uint8Array(['123','xyz',456])
console.log(a) // [123, 0, 200]
这里的’123’会被正常输出,而’xyz’则因为无法转换输出0,而456是因为8位职能表示0-255的整数,因此如果要正常输出,则需将new Uint X Array改为16位或32位。
除了这两种创建方式外,还有一种不常用的方式。ArrayBuffer,传入一块内存指针来创建数组。ArrayBuffer的功能和C语言中的malloc相似,申请一块连续的内存,只不过它不需要手动释放内存。ArrayBuffer的返回值是一个封装成了对象的指针,下面是使用例子:
let buf = new ArrayBuffer(4)
let a = new Uint16Array(buf)
console.log(a)
这里输出的结果是:
这个测试我就不截图了,a这个数组只有两个元素。因为Uint16Array是16位的,也就是每个元素占两个字节。而之前申请的内存控件是4个字节,因此生成的数组只有两个元素。
实例
说了这么多,相信你也大概了解了Javascript中的“强类型数组”是个什么东西,那么让我们回到开始的那道题,new一个强类型的数组会自动的把数组内的元素都初始化为0,因此我们无需再去使用需要通过join和split填充的Array对象,只需要new一个Uint8Array无符号的整形,然后进行map方法改变数组内的值即可:
let arr = new Uint8Array(100).map((item, index) => index)
console.log(arr)
这样输出的arr为:
这样使用Javascript的”强类型数组“也很方便的完成了题目的要求。
结语
这篇文章主要是介绍Javascript中的“强类型数组”的基本概念以及它的一些使用方法,如果想要深入研究,可以去查阅官方文档。
附录
参考文章
拓展阅读
javascript中的稀疏数组(sparse array)和密集数组
关于题目的另外解法
除了使用join,split以及创建一个“强类型数组”外,这道题目还有另外两种方法可以解决。
- 使用间歇性定时器setInterval
let a = [],
i = 0
let interval = setInterval(function() {
i < 100 ? a.push(i++) : clearInterval(interval)
}, 0)
console.log(a)
通过一个计数器来进行自增push值。
2.使用ES6的Array.from方法
let a = Array.from(Array(100).keys())
console.log(a)
这段代码还可以简写为:
let a = [...Array(100).keys()]
console.log(a)
个人更推荐使用ES6的[…Array(100).keys()]
这种方法
- Inhaltsverzeichnis
- Übersicht