文档章节

JavaScript 标准之 Map对象

w-rain
 w-rain
发布于 10/10 15:53
字数 1849
阅读 582
收藏 9

    

    概览:

  •             前言
  •             定义
  •             语法
  •             描述
  •             属性
  •             Map实例            

     前沿

        一直以来使用数组和对象来定义数据模型,前几天在翻阅ES6语法的时候,突然发现有一种Map对象对操作键值对特别好用,而且代码更简洁明了,简直太棒了。今天,我们就来一步步了解什么是Map对象,详细给大家介绍一下Map对象的属性和方法。希望大家以后再数据操纵方法多一种解决问题的方法,这是ECMAScript 6 新增的数据结构。

     定义

   Map对象保存键/值对,是键/值对的集合。任何值(对象或者原始值) 都可以作为一个键或一个值。Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应。

     语法

mapObj = new Map([iterable]);

         iterable 可以是一个数组或者其他 iterable 对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Mapnull 会被当做 undefined

     描述

  •         集合中的键和值可以是任何类型。如果使用现有键向集合添加值,则新值会替换旧值。
  •         ObjectMap 对象的对比:

            相似点: 都允许你按键存取一个值、删除键、检测一个键是否绑定了值。
            不同点:

                       1. 一个对象的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。
                       2. Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map对象是按插入的顺序返回键值。
                       3. 通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值对个数只能手动计算。
                       4. Map 是可迭代的,而 Object 的迭代需要先获取它的键数组然后再进行迭代。
                       5. Object 都有自己的原型,所以原型链上的键名有可能和对象上的键名产生冲突。虽然 ES5 开始可以用 map = Object.create(null) 来创建一个没有原型的对象,但是这种用法不太常见。
                       6. Map 在频繁增删键值对的场景下会有些性能优势。

    属性

                下表列出了Map对象的属性

属性 描述
构造函数 -get Map[@@species] 指定创建映射的函数,本构造函数用于创建派生对象。
原型(Map.prototype) 为映射返回对原型的引用, 表示Map构造器的原型。 允许添加属性从而应用于所有的Map对象。
size (Map.length) 返回映射中的元素数。

    Map实例

           所有的Map实例都会继承自Map.prototype

        属性

                     下表列出了Map对象实例的属性

属性 描述
Map.prototype.constructor 返回一个函数,它创建了实例的原型。默认是Map函数。
Map.prototype.size 返回Map对象的键/值对的数量。

 

        方法

                    下表列出了Map对象实例的方法

方法 描述
Map.prototype.clear() 移除Map对象的所有键/值对。
Map.prototype.delete(key)

移除指定键相关联的值,并且返回该值,该值在之前会被Map.prototype.has(key)返回为true。之后再调用Map.prototype.has(key)会返回false。

Map.prototype.entries() 返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。
Map.prototype.forEach(callbackFn[ , thisArg]) 按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。如果为forEach提供了thisArg,它将在每次回调中作为this值。
Map.prototype.get(key) 返回指定键的值,如果不存在返回undefined。
Map.prototype.has(key) 返回一个布尔值,表示Map实例是否包含键对应的值,如果包含指定元素,返回true。
Map.prototype.keys() 返回一个新的 Iterator对象,它按插入顺序包含了Map对象中每个元素的键。
Map.prototype.set(key, value) 设置Map对象中指定键的值,并返回该Map对象。
Map.prototype.values() 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。
Map.prototype[@@iterator] 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。

 

        示例

                     Map对象类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

let a = new Map();
let b = {p: 'Hello World'};

a.set(b,"content");
a.get(b);                 //"content"

a.has(b);                //true
a.delete(b);             //true
a.has(b);                //false

                作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

let map = new Map([
  ['first', 'aaaaaaaaaaaaa'],
  ['second','bbbbbbbbbbbbb']
]);

map.size();                 // 2
map.has('first');           // true
map.get('first');           // "aaaaaaaaaaaaa"
map.has('second');          // true
map.get('second');          // "bbbbbbbbbbbbb"

               如果对同一个键多次赋值,后面的值将覆盖前面的值。

let map = new Map();

map.set(1, 'aaa');
map.set(1, 'bbb');

map.get(1)         

// "bbb"

                如果读取一个未知的键,则返回undefined!!!注意,只有对同一个对象的引用,Map结构才将其视为同一个键。Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。

let map =new Map();

map.get('abc');         // undefined
map.set(['a'], 555);
map.get(['a'])          // undefined


const k1 = ['a'];
const k2 = ['a'];

map
.set(k1, 111)
.set(k2, 222);

map.get(k1);            // 111
map.get(k2);            // 222

                  Map.clear() 方法清除所有成员,没有返回值。

let map = new Map();

map.set('foo', true);
map.set('bar', false);

map.size();             // 2
map.clear();          
map.size();             // 0

                  Map对象遍历方法示例

let  map = new Map([
  ['first',  'aaa'],
  ['second',  'bbb'],
]);

// map.keys()方法

for (let key of map.keys()) {
  console.log(key);
}

//  first
//  second

// map.values()方法

for (let value of map.values()) {
  console.log(value);
}

// "aaa"
// "bbb"

//map.entries() 方法

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

// "first"  "aaa"
// "second"  "bbb"


//等同于使用map.entries()方法

for (let [key, value] of map) {
  console.log(key, value);
}

// "first"   "aaa"
// "second"  "bbb"

//数组结构可以使用扩展运算符(...)

[...map.keys()]

//["first","second"]

[...map.values()]

// ["aaa","bbb"]

[...map.entries()]

// [["first",  "aaa"],["second",  "bbb"]]

[...map]

//[["first",  "aaa"],["second",  "bbb"]]

                结合数组的map() 和filter()方法,可以实现对Map的遍历和过滤(Map本身没有map()和filter()方法)

let  myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

let newMap = new Map(
  [...myMap].filter(([key, value]) => value < 3)
);

// Map(2) {"thing1" => 1, "thing2" => 2}

let newMap2 = new Map(
  [...myMap].map(([key, value]) => [key, value * 2])
    );

// Map(3) {"thing1" => 2, "thing2" => 4, "thing3" => 6}

                 Map对象还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。

let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

map.forEach(function(value, key, map) {
  console.log("Key: %s, Value: %s", key, value);
});

// Key: thing1, Value: 1
// Key: thing2, Value: 2
// Key: thing3, Value: 3

                forEach方法还可以接受第二个参数,用来绑定this。

let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);

let reporter = {
  report: function(key, value) {
    console.log("Key: %s, Value: %s", key, value);
  }
};

map.forEach(function(value, key, map) {
  this.report(key, value);
}, reporter);

// Key: thing1, Value: 1
// Key: thing2, Value: 2
// Key: thing3, Value: 3

 

 

    参考文献

          转载时请注明:来自w-rain的个人博客

© 著作权归作者所有

共有 人打赏支持
w-rain
粉丝 27
博文 53
码字总数 46145
作品 0
成都
程序员
私信 提问
加载中

评论(1)

杨哥哥
杨哥哥
不错
JavaScript学习记录day4-Map、Set和iterable

JavaScript学习记录day4-Map、Set和iterable [TOC] JavaScript的默认对象表示方式可以视为其他语言中的或的数据结构,即一组键值对。 但是JavaScript的对象有个小问题,就是键必须是字符串。...

ygqygq2
06/29
0
0
[译] 论 Rust 和 WebAssembly 对源码地址索引的极限优化

原文地址:Oxidizing Source Maps with Rust and WebAssembly 原文作者:Nick Fitzgerald 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:D-kylin Tom Tromey 和我尝...

LeviDing
07/16
0
0
[JavaScript]-Array构造的数组使用map为何失效?

[示例] 假设你需要生成一个从0到99的数组。你要怎么做呢?下面是一种解法: 看到这种使用传统的for循环的方式会有点不大习惯。事实上,各种高阶函数,像forEach, map, filter, reduce足以写出...

xiaoLoo
06/27
0
0
Emscripten教程之C++和JavaScript绑定(三)

翻译:云荒杯倾 Embind用于绑定C++函数和类到JavaScript,这样编译代码就能在js中以一种很自然的方式来使用。Embind也支持从C++调JavaScript的class。 Embind支持绑定大多数C++的结构,包括C...

云荒杯倾
2017/09/18
0
0
ES6面试、复习干货知识点汇总(全)

近期在复习ES6,针对ES6新的知识点,以问答形式整理一个全面知识和问题汇总。(全干货,适合对ES6有一定理解的同学复习,以及ES6面试。) 一、问:ES6是什么,为什么要学习它,不学习ES6会怎...

StevenLikeWatermelon
12/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java程序员可知为何公司宁花25K重新招人,也不花20K留住老员工?

身在职场,经常会暗自打听同事工资,尤其是得知身边新入职同事的工资居然比自己高,还高出一大截时,心里自然很不平衡,一心想要离职。 那么,为什么公司宁愿花高价招聘新员工也不愿意给老员...

Java填坑路
4分钟前
1
0
阿里云文件存储(NAS)助力业务系统承载双十一尖峰流量

2018天猫双11全球狂欢节,全天成交额再次刷新纪录达到2135亿元,其中总成交额在开场后仅仅用了2分05秒即突破100亿元,峰值的交易量达到惊人的高度,背后离不开阿里云大数据计算和存储能力的支...

阿里云云栖社区
8分钟前
0
0
【windows 找不到“\\192.168.X.X”,请检查拼写是否正确】错误&139端口和445端口区别

今天像往常一样,通过共享盘访问其他主机时,却出现如题的错误,百思不得其解,毕竟没有改动什么配置啊,地址也没输错啊。 然后就在网上看到了一篇博客,才想起来上周末因为考虑到安全问题,...

fang_faye
8分钟前
0
0
示例Express中路由规则及获取请求参数

本次给大家分享一篇基于express中路由规则及获取请求参数的方法,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。如有不足之处,欢迎批评指正。 express中常见的...

前端攻城小牛
12分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部