JS中集合对象(Array、Map、Set)及类数组对象的使用与对比

2024-02-02 12:18

本文主要是介绍JS中集合对象(Array、Map、Set)及类数组对象的使用与对比,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JS中集合对象(Array、Map、Set)及类数组对象的使用与对比
在使用js编程的时候,常常会用到集合对象,集合对象其实是一种泛型,在js中没有明确的规定其内元素的类型,但在强类型语言譬如Java中泛型强制要求指定类型。

ES6引入了iterable类型,Array,Map,Set都属于iterable类型,它们可以使用for…of循环来遍历,都内置forEach方法。

数组
遍历
普通遍历
最简单的一种,也是使用频率最高的一种。

let arr = ['a', 'b', 'c', 'd', 'e']
for (let i = 0; i < arr.length; i++) {
  console.log(i, ' => ', arr[i])
}
1
2
3
4
优化: 缓存数组长度:

let arr = ['a', 'b', 'c', 'd', 'e']
for (let i = 0, len = arr.length; i < len; i++) {
  console.log(i, ' => ', arr[i])
}
1
2
3
4
使用临时变量,将长度缓存起来,避免重复获取数组长度,当数组较大时优化效果才会比较明显。

for-in
这个循环很多人爱用,但实际上,经分析测试,在众多的循环遍历方式中它的效率是最低的。

let arr = ['a', 'b', 'c', 'd', 'e']
for (let i in arr) {
  console.log(i, ' => ', arr[i])
}
1
2
3
4
for-of
这种方式是es6里面用到的,性能要好于forin,但仍然比不上普通for循环。

let arr = ['a', 'b', 'c', 'd', 'e']
let index = 0
for (let item of arr) {
  console.log(index++, ' => ', item)
}
1
2
3
4
5
forEach
数组自带的foreach循环,使用频率较高,实际上性能比普通for循环弱。

let arr = ['a', 'b', 'c', 'd', 'e']
arr.forEach((v, k) => {
  console.log(k, ' => ', v)
})
1
2
3
4
forEach接受第三个参数,指向原数组,没有返回值,对其进行操作会改变原数组对象

let ary = [12, 23, 24, 42, 1]
let res = ary.forEach((item, index, input) => {
   input[index] = item * 10
})
console.log(res) //-->undefined
console.log(ary) //-->会对原来的数组产生改变
1
2
3
4
5
6
如果版本低的浏览器不兼容(IE8-),可以自定义方法实现:

/**
* forEach遍历数组
* @param callback [function] 回调函数;
* @param context [object] 上下文;
*/
Array.prototype.myForEach = function (callback,context) {
  context = context || window;
  if('forEach' in Array.prototype) {
    this.forEach(callback,context)
    return
  }
  // IE6-8下自己编写回调函数执行的逻辑
  for(let i = 0,len = this.length; i < len; i++) {
    callback && callback.call(context, this[i], i, this)
  }
}
let arr = [12, 23, 24, 42, 1]
arr.myForEach((v, k) => {
  console.log(k, ' => ', v)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
map
map会返回一个全新的数组,同样接受第三个参数,如果对其进行操作会改变原数组。

let ary = [12, 23, 24, 42, 1]
let res = ary.map((item, index, input) => {
   return item * 10
})
console.log(res) //-->[120,230,240,420,10]
console.log(ary) //-->[12,23,24,42,1]
1
2
3
4
5
6
如果版本低的浏览器不兼容(IE8-),可以自定义方法实现:

/**
* map遍历数组
* @param callback [function] 回调函数;
* @param context [object] 上下文;
*/
Array.prototype.myMap = function myMap(callback,context){
  context = context || window
  if('map' in Array.prototype) {
    return this.map(callback, context)
  }
  //IE6-8下自己编写回调函数执行的逻辑
  let newAry = []
  for(var i = 0,len = this.length; i < len; i++) {
    if(typeof callback === 'function') {
      var val = callback.call(context, this[i], i, this)
      newAry[newAry.length] = val
    }
  }
  return newAry
}
arr.myMap((v, k) => {
  console.log(k, ' => ', v)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
过滤
filter
对数组中的每个元素都执行一次指定的函数(callback),并且创建一个新的数组,该数组元素是所有回调函数执行时返回值为 true 的原数组元素。它只对数组中的非空元素执行指定的函数,没有赋值或者已经删除的元素将被忽略,同时,新创建的数组也不会包含这些元素。

let arr = [12, 5, 8, 130, 44]
let ret = arr.filter((el, index, array) => {
  return el > 10
})
console.log(ret) // [12, 130, 44]
1
2
3
4
5
map
map也可以作为过滤器使用,不过返回的是对原数组每项元素进行操作变换后的数组,而不是每项元素返回为true的元素集合。

let strings = ["hello", "Array", "WORLD"]
function makeUpperCase(v) {
  return v.toUpperCase()
}
let uppers = strings.map(makeUpperCase)
console.log(uppers) // ["HELLO", "ARRAY", "WORLD"]
1
2
3
4
5
6
some
对数组中的每个元素都执行一次指定的函数(callback),直到此函数返回 true,如果发现这个元素,some 将返回 true,如果回调函数对每个元素执行后都返回 false ,some 将返回 false。它只对数组中的非空元素执行指定的函数,没有赋值或者已经删除的元素将被忽略。

// 检查是否有数组元素大于等于10:
function isBigEnough(element, index, array) {
  return (element >= 10)
}
let passed1 = [2, 5, 8, 1, 4].some(isBigEnough) // passed1 is false
let passed2 = [12, 5, 8, 1, 4].some(isBigEnough) // passed2 is true
1
2
3
4
5
6
every
对数组中的每个元素都执行一次指定的函数(callback),直到此函数返回 false,如果发现这个元素,every 将返回 false,如果回调函数对每个元素执行后都返回 true ,every 将返回 true。它只对数组中的非空元素执行指定的函数,没有赋值或者已经删除的元素将被忽略。

// 测试是否所有数组元素都大于等于10:
function isBigEnough(element, index, array) {
  return (element >= 10)
}
let passed1 = [12, 5, 8, 1, 4].every(isBigEnough) // passed1 is false
let passed2 = [12, 15, 18, 11, 14].every(isBigEnough) // passed2 is true
1
2
3
4
5
6
排序
let arr = ['a', 1, 'b', 3, 'c', 2, 'd', 'e']
console.log(arr) // ["a", 1, "b", 3, "c", 2, "d", "e"]
console.log(arr.reverse()) // 反转元素(改变原数组) // ["e", "d", 2, "c", 3, "b", 1, "a"]
console.log(arr.sort()) // 对数组元素排序(改变原数组) // [1, 2, 3, "a", "b", "c", "d", "e"]
console.log(arr) // [1, 2, 3, "a", "b", "c", "d", "e"]
1
2
3
4
5
sort自定义排序
let arr = [1, 100, 52, 6, 88, 99]
let arr1 = arr.sort((a, b) => a-b) // 从小到大排序
console.log(arr1) // [1, 6, 52, 88, 99, 100]
let arr2 = arr.sort((a, b) => b-a) // 从大到小排序
console.log(arr2) // [100, 99, 88, 52, 6, 1]
console.log(arr) // 原数组也发生改变
1
2
3
4
5
6
搜索
let arr = [12, 5, 4, 8, 1, 4]
arr.indexOf(4) // 2,从前往后搜索,返回第一次搜索到的数组下标,搜索不到返回-1
arr.lastIndexOf(4) // 5,从后往前搜索,返回第一次搜索到的数组下标,搜索不到返回-1
arr.indexOf(0) // -1
1
2
3
4
增删、清空操作
添加元素
let arr = ['a', 'b', 'c', 'd', 'e']
arr.push(10, 11) // 模仿栈进行操作,往数组末尾添加一个或多个元素(改变原数组)
arr.unshift(0, 1) // 模仿队列进行操作,往数组前端添加一个或多个元素(改变原数组)
console.log(arr) // [0, 1, "a", "b", 'c', "d", "e", 10, 11]
1
2
3
4
删除元素
arr.pop() // 移除最后一个元素并返回该元素值(改变原数组)
arr.shift() // 移除最前一个元素并返回该元素值,数组中元素自动前移(改变原数组)
console.log(arr) // ["b", "c", "d"]
1
2
3
清空数组
将数组的length设置为0即可

let arr = ['a', 1, 'b', 3, 'c', 2, 'd', 'e']
arr.length = 0
1
2
length详解:

因为数组的索引总是由0开始,所以一个数组的上下限分别是:0和length-1;

当length属性被设置得更大时,整个数组的状态事实上不会发生变化,仅仅是length属性变大;

当length属性被设置得比原来小时,则原先数组中索引大于或等于length的元素的值全部被丢失。
splice
既可以删除也可以添加元素

let arr = ['a', 'b', 'c', 'd', 'e']
arr.splice(2, 1, 1,2,3)
console.log(arr) // ["a", "b", 1, 2, 3, "d", "e"]
1
2
3
splice(start, len, elems) : 删除并添加元素(改变原数组)

start: 起始位置
len: 删除元素的长度
elems: 添加的元素队列
几种形式:
splice(start, 0, elems) : 从start位置添加元素
splice(start, len) : 从start位置删除len个元素
截取、合并与拷贝
let arr = ['a', 'b', 'c', 'd', 'e']
let arr1 = arr.slice(1, 2) // 以数组的形式返回数组的一部分,注意不包括 end 对应的元素,如果省略 end 将复制 start 之后的所有元素(返回新数组)
let arr2 = arr.concat([1,2,3]); // 将多个数组(也可以是字符串,或者是数组和字符串的混合)连接为一个数组(返回新数组)
console.log(arr) // ["a", "b", "c", "d", "e"]
console.log(arr1) // ["b"]
console.log(arr2) // ["a", "b", "c", "d", "e", 1, 2, 3]
1
2
3
4
5
6
其实slice和concat也可以作为数组的拷贝方法:

arr.slice(0) // 返回数组的拷贝数组,注意是一个新的数组,不是指向
arr.concat() // 返回数组的拷贝数组,注意是一个新的数组,不是指向
1
2
Map
Map是一组键值对的结构,具有极快的查找速度。

创建
方法一: 创建的时候初始化

let mapObj = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
])
console.log(mapObj.size) // 3
1
2
3
4
5
6
方法二: 创建空Map,之后添加元素

let mapObj = new Map()
mapObj.set('a', 1)
mapObj.set('b', 2)
mapObj.set('c', 3)
console.log(mapObj.size) // 3
1
2
3
4
5
注意: Map对象的长度不是length,而是size

基础操作
Map对象的创建、添加元素、删除元素…

mapObj.set('a', 1) // 添加元素
mapObj.delete('d') // 删除指定元素
mapObj.has('a') // true
mapObj.get('a') // 1
1
2
3
4
遍历
使用上面创建的Map进行操作

forEach
同数组的forEach遍历,三个参数分别代表: value、key、map本身

mapObj.forEach((e, index, self) => {
  console.log(index, ' => ', e)
})
1
2
3
打印出:

a  =>  1
b  =>  2
c  =>  3
1
2
3
for-of
for (const e of mapObj) {
  console.log(e)
}
1
2
3
打印出:

["a", 1]
["b", 2]
["c", 3]
1
2
3
注意: for-of遍历出来的是一个数组,其中e[0]为key,e[1]为value

Set
Set和Map类似,但set只存储key,且key不重复。

创建
方法一: 创建的时候初始化

let setObj = new Set([1, 2, 3])
console.log(setObj.size)
1
2
方法二: 创建空Map,之后添加元素

let setObj = new Set()
setObj.add(1)
setObj.add(2)
setObj.add(3)
console.log(setObj.size)
1
2
3
4
5
注意: Map对象的长度不是length,而是size

基础操作
let s = new Set([1, 2, 3])
s.add(3) // 由于key重复,添加不进
s.delete(3) // 删除指定key
console.log(s) // 1 2
1
2
3
4
遍历
使用上面创建的Set进行操作

forEach
Set与Array类似,但Set没有索引,因此回调函数的前两个参数都是元素本身

s1.forEach(function (element, sameElement, set) {
  console.log(element) // element === sameElement
})
// 打印 1 2 3
1
2
3
4
for-of
for (const item of s1) {
  console.log(item)
}
// 打印 1 2 3
1
2
3
4
类数组对象
JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法。而对于一个普通的对象来说:

如果它的所有property名均为正整数,同时也有相应的length属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为“类数组对象”。

形如:

let obj = {
  0: 'qzy',
  1: 22,
  2: false,
  length: 3
}
1
2
3
4
5
6
类数组对象可以使用Array对象原生方法进行操作。

遍历
沿用上述对象进行操作

forEach
Array.prototype.forEach.call(obj, function(el, index){  
   console.log(index, ' => ', el)
})
1
2
3
map
Array.prototype.map.call(obj, function(el, index){  
   console.log(index, ' => ', el)
})
1
2
3
注意: 类数组对象不支持使用for-of进行遍历,否则会报错: [Symbol.iterator] is not a function

增删截取操作
沿用上述对象进行操作

Array.prototype.join.call(obj, '-') // qzy-22-false
Array.prototype.slice.call(obj, 1, 2) // [22]
Array.prototype.push.call(obj, 5) // Object {0: "qzy", 1: 22, 2: false, 3: 5, length: 4}
1
2
3
String也是一个类数组对象
由于字符串对象也存在length,且序号从0开始增加,因此字符串也可以看做一个只读的类数组对象,这意味着String对象可以使用Array的所有原型方法。

let str = 'hello world'
console.log(Array.prototype.slice.call(str, 0, 5)) // ["h", "e", "l", "l", "o"]
1
2
String也可以使用for-of进行遍历
let str = 'hello world'
for (const s of str) {
  console.log(s)
}
1
2
3
4
String独有方法
除了使用Array原型对象的方法,String还包含其他一些自己独有的方法:

与Array使用方法相同的方法

搜索: indexOf()、lastIndexOf()、concat()

转换
toLowerCase()、toUpperCase()

截取
substr(start, len)

substring(start, end)

slice(start, end)

let str = 'hello world'
let ret1 = str.substr(6, 5) // "world"
let ret2 = str.substring(6, 11) // "world"
let ret3 = str.slice(3, 8) // "lo wo"
1
2
3
4
substring 是以两个参数中较小一个作为起始位置,较大的参数作为结束位置。

slice 是第一参数为起始位置,第二参数为结束位置,如果结束位置小于起始位置返回空字符串

console.log(str.substring(11, 6) === str.substring(6, 11)) // true
1
接收负数为参数时:

slice会将它字符串的长度与对应的负数相加,结果作为参数;
substr则仅仅是将第一个参数与字符串长度相加后的结果作为第一个参数;
substring则干脆将负参数都直接转换为0。
let str = 'hello world'
let ret1 = str.substr(-5) // "world"
let ret2 = str.substr(-5, 3) // "wor"
let ret3 = str.substring(6, -1) // "hello"
let ret4 = str.slice(6, -1) // "worl"

console.log(ret1 === str.substr(str.length - 5)) // true
console.log(ret2 === str.substr(str.length - 5, 3)) // true
console.log(ret3 === str.substring(6, 0)) // true
console.log(ret4 === str.slice(6, str.length - 1)) // true
1
2
3
4
5
6
7
8
9
10
正则
match()
replace()
search()
let str = 'hello world'
let ret0 = str.match(/r/) // 非全局搜索,返回匹配的第一个字符串数组(length为1),包括index和input
let ret1 = str.match(/o/g) // 全局搜索,返回匹配的字符串数组,length为搜索到的匹配正则表达式的长度
let ret2 = str.replace(/o/g, 'e') // 全局替换
let ret3 = str.replace(/O/i, 'e') // 不区分大小写,只替换搜索到的第一个字串
let ret4 = str.search(/l/) // 返回搜索到的第一个匹配字串的索引
let ret5 = str.search(/l/g) // 全局无效,同上

console.log(ret0) // ["r", index: 8, input: "hello world"]
console.log(ret1) // ["o", "o"]
console.log(ret2) // "helle werld"
console.log(ret3) // "helle world"
console.log(ret4) // 2
console.log(ret5) // 2
console.log(str) // 不改变源字符串 'hello world'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
转化
Map => Object
let mapObj = new Map([ ['a', 1], ['b', 2], ['c', 3] ])

let obj = {}
for (const item of mapObj) {
  obj[item[0]] = item[1]
}

console.log(obj)
1
2
3
4
5
6
7
8
Set => Array
let setObj = new Set([1, 2, 3])

let arr = []
for (const item of setObj) {
  arr.push(item)
}

console.log(arr)
1
2
3
4
5
6
7
8
Array => String
arr.join(separator)

['a', 'b', 'c', 'd', 'e'].join('')
// toLocaleString 、toString 、valueOf:可以看作是join的特殊用法,不常用
1
2
String => Array
str.split(separator)

'hello world'.split(' ') // ["hello", "world"]
1
参考资料
————————————————
版权声明:本文为CSDN博主「xiaoxiao昱」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u014302759/article/details/78650131

这篇关于JS中集合对象(Array、Map、Set)及类数组对象的使用与对比的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/670679

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]