[TOC]
>[success] # Set集合与Map集合
<br/>
~~~
'数组'一直是'JavaScript'中唯一的'集合类型',也就是'数组类型','JavaScript'的'数组'的功能与其他
语言一样,但在'ES6标准'制定以前,由于可选的'集合类型'有限,'数组'使用的又是'数值型索引',因而经常
被创建'队列'和'栈'。如果开发者们需要使用'非数值型索引',就会用到'非数组对象'的'数据结构',而这
就是'Set集合'和'Map集合'的早期实现。
~~~
<br/>
~~~
集合类型:
1. 'Array'
2. 'Set'
3. 'Map'
~~~
<br/>
>[success] ## Set集合
<br/>
~~~
'Set集合'是一种'无重复元素的列表',开发者们一般不会逐一(东北话:'挨个')'读取数组中的元素',
也不太可能逐一(东北话:'挨个')'访问Set集合中的每个元素',通常的做法是'检测给定的值,在某集合中是否存在'
~~~
<br/>
>[success] ## Map集合
<br/>
~~~
'Map集合'内含多组'键值对',集合中每个元素分别存放着可访问的'键名'和它对应的'值','Map集合'经常被用于
'缓存频繁取用的数据'。
~~~
<br/>
>[success] ## ES5实现Set集合功能 / Map集合
<br/>
~~~
在'ES6'发布之前,开发者们在'ES5'中用'非数组对象'的方式实现了类似的功能。
~~~
<br/>
1. Set集合实现
~~~
// 创建一个空对象,没有prototype属性的对象
let set = Object.create(null);
// 创建一个set对象的属性
set.foo = true;
if(set.foo){ // 检查属性是否存在
// 要执行的代码
}
~~~
<br/>
2. Map集合实现
~~~
// 创建一个空对象,没有prototype属性的对象
let map = Object.create(null);
// 创建一个Map对象的属性
map.foo = "bar";
// 获取已存值
let value = map.foo;
console.log(value) // "bar"
~~~
<br/>
>[warning] ## ES5实现Set集合、Map集合的一些问题
<br/>
~~~
虽然能用'ES5'能实现出'Set集合'和'Map集合',但是非常的'局限性',如果对象的'属性'有限制的话,
例如,'所有对象的属性必须是字符串类型'、'每个键名(key)都是唯一的'。
~~~
<br/>
1. 用`number类型`值作为对象的属性的问题
~~~
// 创建一个空对象
let map = Object.create(null)
// 用number类型值给对象创建属性,并且赋值
map[5] = 'foo'
console.log(map[5]) // foo
// 等同
console.log(map['5']) // foo
~~~
<br/>
2. 用`对象`作为`对象属性`的问题
~~~
// 创建一个空对象
let map = Object.create(null)
// 创建2个对象
let key1 = {}
let key2 = {}
// 用对象当做key值
map[key1] = 'foo'
console.log(map[key1]) // foo
console.log(map[key2]) // foo
~~~
<br/>
`key1`和`key2`会被转换为`对象字符串`【Object,Object】,所以`map[key1]`和`map[key2]`引用的是同一个属性,实际上就是一个`假值`。对于`Map集合`如果他的值是`假值`,会被自动转换(强制转换)成`布尔值false`,`强制转换`本身没有问题,但是应用到下面的场合就会有问题了
<br/>
~~~
// 创建一个对象
let map = Object.create(null);
map.count = 1;
// 这里本意是想检查count是否存在,实际上检查的是count值否等于0
if(map.count){
// 要执行的代码
}
~~~
<br/>
在上面的例子中就有点让人不解,我们到底是判断的`map.count`是否存在,还是判断的`map.count`的值是否`非零`,就会很让人疑惑。 其实上面的例子中,由于值为`1`,所以判断条件进入了`if`中,如果想判断`对象的一个属性值是否存在`尽量不要这样写,可以使用以下的几个方法:
<br/>
3. 判断对象属性是否存在
~~~
1. 使用`in`关键字,该方法可以判断对象的'自有属性'和'继承来的属性'是否存在。
var o = { x: 1 }
console.log("x" in o) // true 自有属性存在
console.log("y" in o) // false 没有这个属性
console.log("toString" in o) // true,是一个继承属性
2. 使用对象的'hasOwnProperty()'方法,该方法只能判断'自有属性是否存在',对于'继承属性会返回false'。
var o = { x: 1 };
o.hasOwnProperty("x"); // true,自有属性中有x
o.hasOwnProperty("y"); // false,自有属性中不存在y
o.hasOwnProperty("toString"); // false,这是一个继承属性,但不是自有属性
~~~
- Javascript基础篇
- Array数组
- 数组插入值
- filter()
- forEach()
- push()
- pop()
- unshift()
- shift()
- valueOf()
- 面向对象思想
- Javascript 面向对象编程(一):封装
- Javascript面向对象编程(二):构造函数的继承
- Javascript面向对象编程(三):非构造函数的继承
- 解构
- 数组的解构赋值
- 对象的解构赋值
- 函数参数解构
- 字符串的解构赋值
- 数值和布尔值的解构赋值
- 圆括号问题
- 字符串.
- split()
- charAt()
- charCodeAt()
- concat()
- indexOf()
- lastIndexOf()
- match()
- replace()
- includes()
- 初识递归
- 渲染ul-li树形结构
- 异步函数解决方案
- 1. callback回调函数
- 2. ES6 - Promise
- JavaScript高级程序设计(书)
- 在html中使用JavaScript
- script标签的位置
- 延迟脚本
- 异步脚本
- <noscript>元素
- 基本概念
- 严格模式
- 变量详解
- 数据类型
- typeof操作符
- undefined类型
- Null类型
- Boolean类型
- Number类型
- 深入了解ES6(书)
- var 、let 、 const
- 字符串与正则表达式
- 字符串
- 正则表达式
- 函数
- 函数形参默认值
- 使用不具名参数
- 函数构造器的增强能力
- 扩展运算符
- name属性
- 明确函数的多重用途
- 块级函数
- 箭头函数
- 尾调用优化
- 扩展的对象功能
- 对象类别
- 对象字面量语法的扩展
- ES6对象新增方法
- 重复的对象属性
- 自有属性的枚举顺序
- 更强大的原型
- 解构:更方便的数据访问
- 为什么要用解构?
- 对象解构
- 数组解构
- 混合解构
- 参数解构
- Symbol与Symbol属性
- 创建Symbol
- Symbol的使用方法
- Symbol全局私有属性
- Symbol与类型强制转换
- Symbol属性检索
- Symbol的一些构造方法
- Set集合与Map集合
- Set集合
- Weak Set集合(弱引用Set集合)
- Map集合
- JS标准内置对象
- Object 构造函数及属性
- Object 构造方法
- Symbol 内建对象类的函数及属性
- Set 构造函数及属性
- Weak Set 构造函数及属性
- JS杂项
- 类数组对象
- Class类的理解和使用