集合引用类型 下

news2024/11/18 20:44:41

目录

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' }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157363.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32-启动文件详解

✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!! 📃个人主页:rivencode的个人主页 🔥系列专栏:玩转FreeRTOS 💬推荐…

python基础篇之数字类型(下)

大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页:lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主lqj_本人擅长微信小程序,前端,vue,等方面的知识https://blog.csdn.net/lbcyllqj?spm1000.2115.3001.5343 哔哩哔哩欢迎关注&…

在vue2使用百度脑图的kityminder-core进行二次开发思维导图,在源码中添加新的命令

需求说明:最近在搞kityminder-core的思维导图,需要增加一个给节点添加文件的功能,一直在研究源码,发现都是通过执行命令的方式实现的。一直卡在新增命令的步骤,搞了好多天了今天找到了如何在源码里新增命令&#xff0c…

leetcode 1807. 替换字符串中的括号内容【python3双指针+哈希表】实现过程分析以及思路整理

题目 给你一个字符串s,它包含一些括号对,每个括号中包含一个非空的键。 比方说,字符串"(name)is(age)yearsold"中,有两个括号对,分别包含键"name"和"age"。 你知道许多键对应的值&…

android实现侧边栏:解决header控件无法操作和底部menuitem点击无效的问题

1:目录结构:(源码和总结都放在b站,链接在底部) 2:实现的大概逻辑: 使用drawerlayout抽屉布局实现,并使用navigationview加载头部和底部 3:核心问题一:header…

用Python来创建7种不同的文件格式

用Python来创建7种不同的文件格式一、用Python来创建7种不同的文件格式1.1、文本文件1.2、CSV文件1.3、Excel文件1.4、压缩文件1.5、XML文件1.6、JSON文件1.7、PDF文件一、用Python来创建7种不同的文件格式 1.1、文本文件 写入 file_name "my_text_file.txt"# 将…

微信小程序——WXML模板语法-条件渲染,列表渲染

一.条件渲染1.wx:if在小程序中,使用wx:if"{{condition}}"来判断是否需要渲染该代码块:也可以用wx:elif和wx:else来添加else判断:实例如下:1.在js文件中定义一个typedata:{type:1 },此时虚拟页面上显示的就是&#xff1a…

二十四、Kubernetes中Deployment(Deploy)控制器详解

1、概述 在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些: ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代 ReplicaSet&#xff…

kafka/bin/kafka-run-class.sh: line 342: exec: java: not found

本来jps看了下,kafka和zookeeper都起来了,手痒,非要换宝塔的进程守护管理器,选目录为/home/kafka,命令为/home/kafka/bin/zookeeper-server-start.sh /home/kafka/config/zookeeper.properties 就在日志里看到 kafk…

马蹄集 整除的总数

整除的总数 难度&#xff1a;白银 时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 输入正整数N和M,其中N<M。求区间[N,M]中可被K整除的总数。 格式 输入格式&#xff1a;输入正整数N,M和K,空格分隔。 输出格式&#xff1a;输出整型 #include <bits/stdc.h&g…

RabbitMQ(二)使用Docker安装

目录1. 拉取 RabbitMQ 镜像2.启动 RabbitMQ 容器3.查看 RabbitMQ 是否启动官网地址&#xff1a;https://www.rabbitmq.com/ 下载地址&#xff1a;https://www.rabbitmq.com/download.html 这篇文章为了方便初学者入门&#xff0c;在 linux 环境下用 docker 直接安装 RabbitMQ&…

【JavaSE】String相关知识

String \ StringBuilder \ StringBufferString的值是不可变的&#xff0c;使用“”或者“”的方法尝试改变String的值并不是在原本的基础上修改&#xff0c;而是赋值给了新的字符串常量引用StringBuffer是线程安全的&#xff0c;使用的是无脑加synchronized的方法这三者的运行速…

10分钟上手一款好用的服务器节点监测工具(Server 酱)

Server 酱简介 Server酱&#xff0c;英文名「ServerChan」&#xff0c;是一款「手机」和「服务器」、「智能设备」之间的通信软件。说人话&#xff1f;就是从服务器、路由器等设备上推消息到手机的工具。开通并使用上它&#xff0c;只需要一分钟&#xff1a; 微信扫码登入设置…

Mysql可视化软件-Navicat和SQLyog

Navicat 可以将mysql可视化的一个软件 可以避免一直在命令行里面敲代码&#xff0c;很难绷 连接 密码写一个你能记住的&#xff0c;不然打不开连接 对应的IP可以是localhost或者127.0.0.1 都是本机 端口号就我们在my.ini写的那个 然后进行我们上面说的操作-新建一个数据库先…

Linux操作系统常用命令

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

【uniapp】记录地址管理页面

uniapp中的地址管理页面 <template><view class"container"><view class"oldaddress" v-for"(item,index) in cardInfo" :key"index"><view class"topview"><view class"name">{{i…

线缆行业单绞机控制算法(详细图解+代码)

在了解单绞机之前需要大家对收放卷以及排线控制有一定的了解,不清楚的可以参看下面几篇博客,这里不再赘述,受水平和能力所限,文中难免出现错误和不足之处,诚恳的欢迎大家批评和指正。 收放卷行业开环闭环控制算法 PLC张力控制(开环闭环算法分析)_RXXW_Dor的博客-CSDN博…

Win10专业版系统Docker安装、配置和使用详细教程

一、win10专业版系统首先需要开启硬件虚拟化及Hyper-V功能&#xff0c;才能进行Docker for Windows软件安装。 如何开启硬件虚拟化&#xff0c;自行百度。可在任务栏中查看虚拟化是否开启。 win10系统&#xff0c;打开控制面板-“应用”-“程序和功能”&#xff0c;开启Hyper-V…

webpack 的基本使用

webpack 的基本使用配置 npm 镜像源创建列表隔行变色案例新建空白项目目录&#xff0c;初始化 package.json 配置文件通过 npm 安装 jquery新建 src 源代码目录index.htmlindex.js检查网页效果webpack 的安装webpack 的安装dependencies 与 devDependencies参数 -S 及 --save参…

【Linux工具】-yum/gdb

yum/gdb一&#xff0c;yum1&#xff0c;简介2&#xff0c;软件下载3&#xff0c;软件删除4&#xff0c;yum源与扩展yum源5&#xff0c;常见选项二&#xff0c;gdb1&#xff0c;简介2&#xff0c;gdb相关指令一&#xff0c;yum 1&#xff0c;简介 在Linux下&#xff0c;下载软…