关于JS数组的常见问题

158 阅读6分钟

最近在补JS的一些基础知识,刚刚看到关于数组Array的地方,就简单的做了一些笔记。

JS的数组和其他语言的数组类似,但是又有些许不同,最大的不同就是JS的数组存储的值类型不是固定的,不像Java或者C中的数组,在创建之前就要说明是一个什么类型的数组,且数组只能存储该类型的值。JS的数组是没有规定数据类型的,你可以在数组的第一项存一个字符串,第二项存一个布尔值等。

1、如何判断一个对象是不是数组?

答:如果是在只有一个网页(只有一个全局作用域),可使用instanceof操作符。如果不止一个全局上下文,ECMAScript提供Array.isArray()。

if(value instanceof Array){
//操作数组
}
if(Array.isArray(value)){
//操作数组
}
2、JS中如何实现栈与队列?

答:在ECMAScript中为数组提供默认的push(),pop()实现推入与弹出,模拟栈;提供push(),shift(),实现尾添加与首删除,模拟队列。同时ECMAScript还为数组提供unshift(),pop(),以实现首添加和尾删除。

3、JS中对数组有哪些排序方法,区别是什么?

答:JS中对数组的排序方法有两种reverse()和sort()。reverse()是对数组的反向排列,也可以说reverse()只是对数组的一个反转。sort()则是对数组大小的一个排序,默认是按照升序排列的,sort()会先将数组的每一个元素都强制转型String,然后比较每一个字符串的大小已决定其先后顺序。但是sort()的按字符串的比较不一定就是正确的,所以一般还会为其传入一个比较函数compare作为参数,compare函数的主要功能就是比较两个数值的大小,其适用于大部分的数据类型,通过返回正负值以判断传入数值的大小。

无论是sort()还是reverse(),返回的都是数组的引用。

4、JS中对数组的搜索有哪些?

答:ECMAScript提供两种搜索数组的方法:按严格相等和按断言函数搜索。

严格相等:ECMAScript提供三个严格相等的搜索方法:indexOf(),lastIndexOf(),includes().除了lastIndexOf()是从尾向前,其余的都是从前向后。

断言函数:断言assert 宏的原型定义在 assert.h 中,其作用是如果它的条件返回错误,则终止程序执行。ECMAScript中的find(),findIndex()就是按照定义的断言函数。

5、迭代方法

ECMAScript中为数组定义5个迭代方法。每一个方法接收两个参数:以每一项为参数运行的函数和可选做函数运行上下文的作用域对象(影响函数中this的值)。

  • every():对数组的每一项都运行传入的函数,如果每一项都返回true,则这个方法返回true。
  • some():对数组每一项都运行传入的函数,如果有一项为true,则该方法返回true.
  • filter():对数组每一项都运行传入的函数,将所有返回true的项组成数组返回
  • forEach():对数组每一项都运行传入的函数,没有返回值
  • map():每一项都运行传入函数,每一项返回结果组成数组。
let number=[1,3,4,5,7,8,9,2,34];
let fillterResult=number.finlter((item,index,array)=>item>2);
console,log(filterResult);//3,4,5,7,8,9,34
6、归并方法

ECMAScript提供两个归并方法:reduce(),reduceRight()。区别在于前者从左往右,后者从右往左。

两个方法都接收两个参数:对每一项都会运行的归并函数,以及可选之为归并起点的初始值。而归并函数又接收4个参数:上一个归并值,当前项,当前项索引,数组本身。有点类似算法中的动态规划,将前面的返回值作为下次的一个参数。

let value=[1,2,3,4,5];
let sum=value.reduce((pre,cur,index,array)=>pre+cur);
console.log(sum)//15
7、定型数组

定型数组(Typed Array)是ECMAScript新增的结构,目的是提升向原生库传输数据的效率。实际上JavaScript并没有定型数组这种类型,它所指的其实是一种特殊的包含数值类型的数组。

定型数组的出现是源于浏览器的发展,人们希望开发出一套JavaScript API在不需要第三方插件的情况下能够充分利用3D图形API和CPU加速,以便在元素上直接渲染出复杂的图形。

后来便有了WedGL(Wed Graphics Library),开发者能够在兼容WedGL的浏览器上运行编写涉及复杂图形的应用程序。但是因为早期的WedGL与JavaScript数组是不匹配的,图形驱动程序API不需要JavaScript默认双精度浮点格式传递它们的值,而JavaScript在内存中的存在格式就是双精度浮点格式。因此WedGL与JavaScript运行时数组的传递往往需要WedGL绑定都需要在目标环境分配的新数组,以其当前格式迭代数组,然后将数值转型为新数组中的适当格式,这无疑就需要消耗大量的时间。

为节省时间,Mozilla(一种浏览器)实现了CanvasFloatArray。这是一个提供JavaScript接口、C语音风格的浮点值数组。JavaScript运行时使用这个类型就可以分配、写入、读取数组。这个数组可以直接传给底层图形驱动程序API,也可以直接从底层获取。最终CanvasFloatArray演变成了Float32Array,也就是现在定型数组中第一个可用类型。

Float32Array实际上是一种“视图”,可以允许JavaScript运行时访问一块名为ArrayBuffer的预分配内存,而ArrayBuffer是所有定型数组及视图引用的基本单位。

定型数组是另一种形式的ArrayBuffer视图,其特点在于它特定于一种ElementType且遵循系统原生的字节序。定型数组的根本目的还是提高与WedGL等原生库交换二进制数据的效率。

Map

在ES6之前JavaScript要保存“键/值”式存储可以使用Object来完成,也可用一个对象分别表示“键”与“值”

1、Map与Object的区别是什么?

在不考虑内存性能的情况下两者是没什么区别的。在考虑内存的情况下,Map会比Object更好一些。

object和map的工程级实现在不同的浏览器中存在着明显的差异,但存储在单个键/值对所占用的内存数量都是会随键的数量线性增加。批量删除或者添加键值对则取决于各浏览器对该类型内存分配的工程实现。在给定固定大小的内存,map会比object多存储50%的键值对。

插入速度上,map会快一些。

查找上object会快一些。

删除上map会更好。