当前位置: 首页 > news >正文

JavaScript学习笔记(六)——Map、Set与iterable

在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意!

如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/学习。


 

Map与Set

Map和Set是ES6标准新增的数据类型。

Map

JavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。

但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是很合理的。

为了解决这个问题,最新的ES6规范引入了新的数据类型Map

 

Map是一组键值对的结构,具有极快的查找速度。举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array:

var names = ['Michael', 'Bob', 'Tracy'];
var scores = [95, 75, 85];

给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,Array越长,耗时越长。

如果用Map实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用JavaScript写一个Map如下:

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95

初始化Map需要一个二维数组,或者直接初始化一个空Map。Map具有以下方法:

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值覆盖掉:

var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam'); // 88

Set

Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。

要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set:

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

重复元素在Set中自动被过滤:

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}

注意数字3和字符串'3'是不同的元素。

通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果:

s.add(4);
s; // Set {1, 2, 3, 4}
s.add(4);
s; // 仍然是 Set {1, 2, 3, 4}

通过delete()方法可以删除元素:

var s = new Set([1, 2, 3]);
s; // Set {1, 2, 3}
s.delete(3);
s; // Set {1, 2}

iterable

遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。

具有iterable类型的集合可以通过新的for...of循环来遍历。

for...of循环是ES6引入的新的语法。用法如下:

var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
    console.log(x);
}
for (var x of s) { // 遍历Set
    console.log(x);
}
for (var x of m) { // 遍历Map
    console.log(x[0] + '=' + x[1]);
}

注意:for...in循环和for...of循环区别:

for...in循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。

当我们手动给Array对象添加了额外的属性后,for...in循环将带来意想不到的意外效果:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
    console.log(x); // '0', '1', '2', 'name'
}

for...in循环将把name包括在内,但Array的length属性却不包括在内。

for...of循环则完全修复了这些问题,它只循环集合本身的元素:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
    console.log(x); // 'A', 'B', 'C'
}

这就是为什么要引入新的for...of循环。

然而,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数。以Array为例:

'use strict';
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    console.log(element + ', index = ' + index);
});

注意,forEach()方法是ES5.1标准引入的,你需要测试浏览器是否支持。

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

var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
    console.log(element);
});

Map的回调函数参数依次为value、key和Map本身:

var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
    console.log(value);
});

如果对某些参数不感兴趣,由于JavaScript的函数调用不要求参数必须一致,因此可以忽略它们。例如,只需要获得Array的Element:

var a = ['A', 'B', 'C'];
a.forEach(function (element) {
    console.log(element);
});

转载于:https://www.cnblogs.com/whucs2012/p/7874319.html

相关文章:

  • 路由器的无线桥接(TP-Link)
  • c++ static 关键字
  • 小记如何修改xen模块
  • 烂泥:Win8如何禁用IE增强功能
  • Keepalived 配置电信/联通双线高可用集群
  • NeHe OpenGL第十课:3D世界
  • Lync 小技巧-17-查询Lync 2013聊天记录
  • RTX 无法刷新组织架构的处理方法总结
  • java18 任务调度
  • redis允许远程访问
  • 分分钟带你玩转 Web Services【1】JAX-WS
  • 7.linux同步服务器 rsync+sersync的配置
  • 【前端】手机端网页自动播放背景音乐相关资料
  • 使用require.js
  • 对Cookie和Session的深入理解
  • es的写入过程
  • Js基础知识(一) - 变量
  • React 快速上手 - 07 前端路由 react-router
  • React中的“虫洞”——Context
  • Sass 快速入门教程
  • Vue学习第二天
  • 从伪并行的 Python 多线程说起
  • 动态魔术使用DBMS_SQL
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 构造函数(constructor)与原型链(prototype)关系
  • 规范化安全开发 KOA 手脚架
  • 排序算法学习笔记
  • 译米田引理
  • 运行时添加log4j2的appender
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 数据库巡检项
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (C语言)逆序输出字符串
  • (LeetCode 49)Anagrams
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (TOJ2804)Even? Odd?
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)3D模板阴影原理
  • (转)nsfocus-绿盟科技笔试题目
  • (转)Sql Server 保留几位小数的两种做法
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .“空心村”成因分析及解决对策122344
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .NET基础篇——反射的奥妙
  • .NET序列化 serializable,反序列化
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • /bin/rm: 参数列表过长"的解决办法
  • @JsonSerialize注解的使用
  • @WebServiceClient注解,wsdlLocation 可配置