集合引用类型 下

2023-11-11

目录

Map

 Map.set()

 Map.get()

 Map.delete()

Map.has()

Map.values()

Map.entries()

Map.clear()

选择Object 还是Map

 数据转换

转为数组

转为 JSON

 对象转为 Map

数组转为 Map 

转为Object 

WeakMap

基本API

弱键

不可迭代

Set

 创建Set实例

Set实例转数组

size属性

add()

 has()

. delete()

clear()

迭代

WeakSet

迭代与扩展操作


Map

映射(Map)是 ECMAScript 6 规范中引入的一种数据结构。这是一种存储键值对列表很方便的方法,类似于其他编程语言中的词典或者哈希表。常用的 Map 方法有:

  • 赋值 set(key, value) 、
  • 获取 get(key) 、
  • 移除指定键名及其对应的值 delete(key) 、
  • 判断是否存在 has(key) 、
  • 获取所有值 values() 、
  • key/value 迭代器 entries()
  • 清空所有键/值对 clear() 等。

JavaScript 的对象 Object,本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键,这给使用带来了很大的限制。为了解决这个问题,ECMAScript 6 引入了 Map 数据结构。它类似于对象,也是键值对的集合,但是""的范围不仅仅局限于字符串,而是各种类型的值(包括对象)都可以当作键。也就是说,Object 结构(对象结构)提供了"字符串—值"的对应,而 Map 结构提供了"值—值"的对应,是一种更完善的 Hash 结构的实现。

 输出结果为:

Map {
  'seo' => {
    keywords: 'infoq、Map',
    description: 'Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)'
  },
  'title' => 'javascript es6的map映射'
}
object

 

 Map.set()

为数据类型 Map 赋值的方法 map.set(key,value),可以用于增加新的键/值对或者修改键/值对,返回整个 Map 对象。

myMap.set(key, value);
  • key:要添加至相应 Map 对象的元素的键。
  • value:要添加至相应 Map 对象的元素的值。

返回值 返回 Map 对象。

    const page_info = new Map()
    // 设置值
    page_info.set("seo", {
        "keywords": "infoq、Map",
        "description": "Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)"
    });
    console.log(page_info);
    page_info.set("seo", "seo信息");
    console.log(page_info);

 Map.get()

使用 get(key) 获取键值,如果获取的 key->value 不存则返回 undefined 。

myMap.get(key);
  • key:必须参数,也是它唯一的参数,要从目标 Map 对象中获取的元素的键。

返回值 返回一个 Map 对象中与指定键相关联的值,如果找不到这个键则返回 undefined

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    const title = page_info.get("title");
    const seo_info = page_info.get("seo");
    console.log(title);      // javascript es6的map映射
    console.log(seo_info);   // undefinedC

 Map.delete()

map.delete(key) 删除指定 key 的键值对,返回成功或失败结果,删除成功返回 true,删除失败返回 false

myMap.delete(key);
  • key:必须,从 Map 对象中移除的元素的键。

返回值 返回值为一个 Boolean 值,如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    page_info.set("author", "infoq");
    console.log(page_info);         // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }

    const deleted_author = page_info.delete("author");
    const deleted_seo = page_info.delete("seo");
    console.log(deleted_author);   // true
    console.log(deleted_seo);      // false
    console.log(page_info);

Map.has()

判断指定key是否存在。

语法

myMap.has(key);
  • key:必填. 用来检测是否存在指定元素的键值。

返回值 返回值为一个 Boolean 值,如果指定元素存在于 Map 中,则返回 true,其他情况返回 false

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    console.log(page_info);         // Map { 'title' => 'javascript es6的map映射' }

    console.log(page_info.has("title"));   // true
    console.log(page_info.has("seo"));     // false

Map.values()

获取所有键的值。

语法

myMap.values()

返回值 一个新的 Map 可迭代对象。

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    page_info.set("author", "infoq");
    console.log(page_info.values());       // [Map Iterator] { 'javascript es6的map映射', 'infoq' }

Map.entries()

返回一个新的包含 [key, value] 对的 Iterator 对象,返回的迭代器的迭代顺序与 Map 对象的插入顺序相同。

语法

myMap.entries()

返回值一个新的 Map 迭代器对象。

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    page_info.set("author", "infoq");
    console.log(page_info.entries());

Map.clear()

移除Map对象中的所有元素。

语法

myMap.clear();

返回值 清除所有元素,返回 undefined 。

    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    page_info.set("author", "infoq");
    page_info.clear();
    console.log(page_info);  // Map {}

选择Object 还是Map

map是键值的映射,对象是作为属性进行保存。

  • 内存占用: 给定固定大小的内存,Map 大约可以比Object 多存储50%的键/值对。
  • 插入性能:向Object 和Map 中插入新键/值对的消耗大致相当,Map稍快一点。
  • 查找速度:如果只包含少量键/值对,则Object 有时候速度更快。在把Object 当成数组使用的情况下(比如使用连续整数作为属性),浏览器引擎可以进行优化,在内存中使用更高效的布局。这对Map 来说是不可能的。对这两个类型而言,查找速度不会随着键/值对数量增加而线性增加。如果代码涉及大量查找操作,那么某些情况下可能选择Object 更好一些。
  • 删除性能:使用delete 删除Object 属性的性能一直以来饱受诟病,目前在很多浏览器中仍然如此。为此,出现了一些伪删除对象属性的操作,包括把属性值设置为undefined 或null。但很多时候,这都是一种讨厌的或不适宜的折中。而对大多数浏览器引擎来说,Map 的delete()操作都比插入和查找更快。如果代码涉及大量删除操作,那么毫无疑

 数据转换

Map 是一个集合,可以与数组、对象进行转换。

转为数组

Map 转为数组最方便方法是使用扩展运算符 ...,如下:

const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log([...page_info]);  // [ [ 'title', 'javascript es6的map映射' ], [ 'author'

转为 JSON

Map 转为 JSON ,步骤是先把 Map 转为对象,即前面的 mapToObj,然后使用 JSON.stringify 方法,如下:

function mapToObj(map) {
    const obj = Object.create(null);
    map.forEach((v,k)=>{
        obj[k] = v;
    });
    return obj;
}
function mapToJson(map){
    return JSON.stringify(mapToObj(map));
}
const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log( mapToJson(page_info));   // {"title":"javascript es6的map映射","author":"infoq"}

 对象转为 Map

对象转为 Map 映射通过 Object.entries()

const page_info = {
    title:"javascript es6的map映射",
    author:"infoq"
};
console.log(new Map(Object.entries(page_info)));  // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }

数组转为 Map 

将数组传入 Map 构造函数即可,即 new Map(array),如下:

const page_info = [
    ["title","javascript es6的map映射"],
    ["author","infoq"]
];
console.log(new Map(page_info)); // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }

转为Object 

    function mapToObj(map) {
        const obj = Object.create(null);
        map.forEach((v, k) => {
            obj[k] = v;
        });
        return obj;
    }
    const page_info = new Map();
    page_info.set("title", "javascript es6的map映射");
    page_info.set("author", "infoq");

    console.log(mapToObj(page_info));

WeakMap

WeakMap 是Map 的“兄弟”类型,其API 也是Map 的子集。WeakMap 中的“weak”(弱),描述的是JavaScript 垃圾回收程序对待“弱映射”中键的方式。

基本API

可以使用new 关键字实例化一个空的WeakMap:

const wm = new WeakMap();

弱映射中的键只能是Object 或者继承自Object 的类型,尝试使用非对象设置键会抛出TypeError。值的类型没有限制。

const key1 = {id: 1},
		 key2 = {id: 2},
		 key3 = {id: 3};
// 使用嵌套数组初始化弱映射
const wm1 = new WeakMap([
	[key1, "val1"],
	[key2, "val2"],
	[key3, "val3"]
]);
alert(wm1.get(key1)); // val1
alert(wm1.get(key2)); // val2
alert(wm1.get(key3)); // val3

键不是对象时,报错:

// 初始化是全有或全无的操作
// 只要有一个键无效就会抛出错误,导致整个初始化失败
const wm2 = new WeakMap([
	[key1, "val1"],
	["BADKEY", "val2"],
	[key3, "val3"]
]);
// TypeError: Invalid value used as WeakMap key
typeof wm2;
// ReferenceError: wm2 is not defined

初始化之后可以使用set()再添加键/值对,可以使用get()has()查询,还可以使用delete()删除。

弱键

WeakMap 中“weak”表示弱映射的键是“弱弱地拿着”的。意思就是,这些键不属于正式的引用,不会阻止垃圾回收。但要注意的是,弱映射中值的引用可不是“弱弱地拿着”的。只要键存在,键/值对就会存在于映射中,并被当作对值的引用,因此就不会被当作垃圾回收。

const wm = new WeakMap();
wm.set({}, "val");

set()方法初始化了一个新对象并将它用作一个字符串的键。因为没有指向这个对象的其他引用,所以当这行代码执行完成后,这个对象键就会被当作垃圾回收。然后,这个键/值对就从弱映射中消失了,使其成为一个空映射。在这个例子中,因为值也没有被引用,所以这对键/值被破坏以后,值本身也会成为垃圾回收的目标。

即当这个对象键没有引用时,会被回收,导致这个键值对也会被回收

不可迭代

因为WeakMap 中的键/值对任何时候都可能被销毁,所以并没有给WeakMap提供迭代键值对的能力。
所以无法迭代,所以也不可能在不知道对象引用的情况下从弱映射中取得值。即便代码可以访问WeakMap 实例,也没办法看到其中的内容。

WeakMap实例之所以限制只能用对象作为键,是为了保证只有通过键对象的引用才能取得值。如果允许原始值,那就没办法区分初始化时使用的字符串字面量和初始化之后使用的一个相等的字符串了。
 

Set

ECMAScript 6 新增的 Set 是一种新集合类型,为这门语言带来集合数据结构。Set 在很多方面都像是加强的 Map,这是因为它们的大多数 API 和行为都是共有的。

 创建Set实例

使用 new 关键字和 Set 构造函数可以创建一个空集合:

const s = new Set();

如果想在创建的同时初始化实例,则可以给 Set 构造函数传入一个可迭代对象,其中需要包含插入到新集合实例中的元素(Set 可以包含任何 JavaScript 数据类型作为值):

const s = new Set(["val1", 1, true, {}, undefined, function fun() {}]);

注意:Set结构不会添加重复的值

const s = new Set([1, 1, 2, 3, 4, 4, 5, 6, 7, 4, 2, 1]);
Array.from(s); //  [1, 2, 3, 4, 5, 6, 7]

经常用Set解决数组去重问题

const arr = [1, 2, 3, 3, 4, 5, 4, 4, 2, 1, 3];
Array.from(new Set(arr)); // [1, 2, 3, 4, 5]

Set实例转数组

const s = new Set([1, 2, 3]);
Array.from(s); // [1, 2, 3]

size属性

size: 获取Set实例的元素个数:

const s = new Set([1, 2, 3]);
s.size; // 3

add()

add(): 添加元素:

const s = new Set();
s.add(1).add(2).add(3);
Array.from(s); // [1, 2, 3]

 has()

has(): 查询Set实例是否存在某元素(返回布尔值):

const s = new Set();
s.add(1).add(2).add(3);
s.has(1); // true

. delete()

delete(): 删除Set实例中某个元素(返回布尔值):

const s = new Set();
s.add(1).add(2);
s.delete(1);
Array.from(s); // [2]

clear()

clear(): 清空Set实例:

const s = new Set();
s.add(1).add(2).add(3);
Array.from(s); // [1, 2, 3]
s.clear();
Array.from(s); // []

迭代

  • keys():返回键名;
  • values(): 返回键值;
  • entries(): 返回键值对;
  • 键名=键值
const s = new Set();
s.add(1).add(2).add(3);
Array.from(s.keys()); // [1, 2, 3]
Array.from(s.values()); // [1, 2, 3]
Array.from(s.entries()); // [[1, 1], [2, 2], [3, 3]]

for-of:

const s = new Set();
s.add(1).add(2).add(3);
for (const i of s) {
	console.log(i);
}
// 1
// 2
// 3

forEach

const s = new Set();
s.add(1).add(2).add(3);
s.forEach((value, key) => console.log(key + ' : ' + value));
// 1 : 1
// 2 : 2
// 3 : 3

WeakSet

WeakSet 是Set 的“兄弟”类型,其API 也是Set 的子集。WeakSet 中的“weak”(弱),描述的是JavaScript 垃圾回收程序对待“弱集合”中值的方式。

可以使用new 关键字实例化一个空的WeakSet

const ws = new WeakSet();

弱集合中的值只能是Object 或者继承自Object 的类型,尝试使用非对象设置值会抛出TypeError。
如果想在初始化时填充弱集合,则构造函数可以接收一个可迭代对象,其中需要包含有效的值。可迭代对象中的每个值都会按照迭代顺序插入到新实例中:

const val1 = {id: 1},
	  val2 = {id: 2},
	  val3 = {id: 3};
// 使用数组初始化弱集合
const ws1 = new WeakSet([val1, val2, val3]);
alert(ws1.has(val1)); // true
alert(ws1.has(val2)); // true
alert(ws1.has(val3)); // true

初始化之后可以使用add()再添加新值,可以使用has()查询,还可以使用delete()删除。弱值性质与不可迭代性质与WeakMap的原理相同。

迭代与扩展操作

有4 种原生集合类型定义了默认迭代器:

  • Array
  • 所有定型数组
  • Map
  • Set

意味着上述所有类型都支持顺序迭代,都可以传入for-of 循环:

for (const iterableThing of iterableThings) {
	for (const x of iterableThing) {
		console.log(x);
	}
}

意味着所有这些类型都兼容扩展操作符。扩展操作符在对可迭代对象执行浅复制时特别有用,只需简单的语法就可以复制整个对象:

let arr1 = [1, 2, 3];
let arr2 = [...arr1];
console.log(arr1); // [1, 2, 3]
console.log(arr2); // [1, 2, 3]
console.log(arr1 === arr2); // false

对于期待可迭代对象的构造函数,只要传入一个可迭代对象就可以实现复制

let map1 = new Map([[1, 2], [3, 4]]);
let map2 = new Map(map1);
console.log(map1); // Map {1 => 2, 3 => 4}
console.log(map2); // Map {1 => 2, 3 => 4}

也可以构建数组的部分元素

let arr1 = [1, 2, 3];
let arr2 = [0, ...arr1, 4, 5];
console.log(arr2); // [0, 1, 2, 3, 4, 5]

浅复制意味着只会复制对象引用,复制指针,指向的还是同一个对象。

let arr1 = [{}];
let arr2 = [...arr1];
arr1[0].foo = 'bar';
console.log(arr2[0]); // { foo: 'bar' }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

集合引用类型 下 的相关文章

  • IPC:消息队列

    消息队列 gcc messageQueue c o mq lrt mqd t mq send mqd t mqdes const char msg ptr size t msg len unsigned msg prio msg prio
  • OpenCV 实现读取摄像头、视频读取保存 (C++)

    一 读取摄像头 重点语句 VideoCapture imshow 原理 使用VideoCapture语句读取摄像头 再利用while一次次将VideoCapture所读取的数据利用imshow语句一帧帧地读取出来 include

随机推荐

  • 基于多任务学习和GCN的交通路网出租车需求预测

    1 文章信息 文章题目为 Multitask Learning and GCN Based Taxi Demand Prediction for a Traffic Road Network 是一篇发表在Sensors期刊上的有关基于多任务
  • 解决vista和win10在windows服务中交互桌面权限问题:穿透Session 0 隔离

    服务 Service 对于大家来说一定不会陌生 它是Windows 操作系统重要的组成部分 我们可以把服务想像成一种特殊的应用程序 它随系统的 开启 关闭 而 开始 停止 其工作内容 在这期间无需任何用户参与 Windows 服务在后台执行
  • python数据分析面试_python数据分析面试

    1 如何利用SciKit包训练一个简单的线性回归模型 利用linear model LinearRegression 函数 Create linear regression object regr linear model LinearRe
  • vs code配置c语音环境

    要在VS Code中配置C语言环境 您可以按照以下步骤进行操作 安装C C 扩展程序 在VS Code中 您可以通过搜索 C C 来找到C C 扩展程序 安装该扩展程序后 您可以在VS Code中使用C C 语言编写代码 创建C C 项目
  • C++入门-----拷贝构造

    学习目标 1 拷贝构造函数的概念及使用 2 特征 3 注意的点 3 1 防止无穷递归 3 2 防止原对象被修改 4 默认生成拷贝构造 4 1 浅拷贝 4 2 为什么要自己实现拷贝构造函数 4 3 其对于内置类型和自定义类型的处理方式 5 总
  • vue响应式数据-修改对象的属性值,视图不更新

    目录 bug复现 原因 怎么在console中判断是不是响应式数据 怎样才能设置为响应式数据 bug复现 在代码中给一个对象 新增多个属性并赋值 然后在另一个方法中修改对象其中一个属性的值 发现数据改变 页面视图并没有更新 data ret
  • 在Vue.js的public目录下的index.html文件中,可以使用EJS(Embedded JavaScript)模板语法来插入变量。

    这个示例中 和被用于插入对应的变量 这些变量将被EJS模板引擎根据环境和配置进行替换 同样 会将htmlWebpackPlugin插件的options title属性插入到
  • vue中动态水印

    效果 一 根元素div上增加 div class rootZhy div 二 增加方法 watermarkZhy content let container document body let width 120px let height
  • BeanCreationException: Error creating bean with name ‘configurationPropertiesBeans‘ defined in class

    1 现象 启动 SpringCloud项目时报错 2 解决方案 2 1 spring cloud dependencies添加到dependencyManagement标签
  • STM32开发(六)STM32F103 通信 —— RS485 Modbus通信编程详解

    上一篇 主目录 下一篇 文章目录 一 基础知识点 二 开发环境 三 STM32CubeMX相关配置 1 STM32CubeMX基本配置 2 STM32CubeMX RS485 相关配置 四 Vscode代码讲解 五 结果演示以及报文解析 六
  • Spring Boot 添加拦截器

    文章目录 Spring Boot 添加拦截器 方法1 新增拦截器 配置拦截器 方法2 新增拦截器 配置拦截器 拦截所有响应 Spring Boot 添加拦截器 介绍一下在Spring Boot 2 0 0以上版本如何添加拦截器 方法1 新增
  • html烟花代码在线编程,canvas实现烟花的示例代码

    前言 马上过年了 我打算在后台里面偷偷地埋个新春祝福 放烟花的彩蛋 项目是基于react typescript的 因此最后封装成了一个组件 设置好开启时间就可以显示了 目录结构 目录结构大致如下 我们将烟花分为两个阶段 一个是未炸开持续上升
  • Python不同excel的合并操作

    Python不同excel的合并操作 23333333333我的第一篇博客 有一点瞎搞的感觉 0 0 问题描述 对7个类似下图的Excel进行合并 合并的最终效果 Excel文件需要可以找我 技术分析 获取表格中相同格式的部分进行操作 对除
  • 华为OD机试真题 Java 实现【服务中心选址】【2023Q1 100分 】

    一 题目描述 一个快递公司希望在一条街道建立新的服务中心 公司统计了该街道中所有区域在地图上的位置 并希望能够以此为依据为新的服务中心选址 使服务中心到所有区域的距离的总和最小 给你一个数组 positions 其中 positions i
  • 苏宁图书爬虫第一版

    最近一直在忙于工作 当我知道这些都是借口 毕竟某些博主大佬深夜还在更新订阅号更新微博 或许这就是自制力的差距吧 不啰嗦了 今天要写的主要是一篇关于如何爬取 苏宁图书 当然只是半成品 但是大部分问题都已经解决 在这里记录一下发生过的问题 以免
  • 专题五 Redis高并发场景

    介绍 Redis高并发场景 如果直接去学会比较抓不住头绪 因此本文将一步步介绍Redis的高并发的步骤演进 首先解释synchronized不适合在分布式场景 因为synchronized只适用自身的JVM 因此在分布式场景下多台机器的情况
  • 用IEDA开发WEB项目发生的java.lang.NoClassDefFoundError解决方法

    编译的时发生了这个问题 然后上网上百度了一下 一下出自于别人的博客 一 第一种 也是新手容易犯的错误 那就是classpath环境变量配置错误 这个错误在我最开始学习Android的时候就遇到过 弄的焦头烂额的 解决办法 在系
  • 华为机试:计算某字母出现次数 (不区分大小写)

    一 题目 描述 写出一个程序 接受一个由字母 数字和空格组成的字符串 和一个字母 然后输出输入字符串中该字母的出现次数 不区分大小写 字符串长度小于500 输入描述 第一行输入一个由字母和数字以及空格组成的字符串 第二行输入一个字母 输出描
  • 【华为OD机试】数字最低位排序【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 给定一个非空数组 列表 起元素数据类型为整型 请按照数组元素十进制最低位从小到大进行排序 十进制最低位相同的元素 相对位置保持不变 当数组元素为负值时 十进制最低为等
  • 集合引用类型 下

    目录 Map Map set Map get Map delete Map has Map values Map entries Map clear 选择Object 还是Map 数据转换 转为数组 转为 JSON 对象转为 Map 数组转