symbol、set和map
一、symbol
symbol是ES6中新增的一种数据类型(原始数据类型)
常见的七种数据类型:number、string、boolean、null、undefined、object、symbol
symbol是一个独一无二的值
也就是说使用同一个代码产生的两个symbol类型也是不相同的
let s=Symbol();
console.log(s);//Symbol()
let s1=Symbol();
console.log(s==s1);//false 两个值不想等 独一无二
symbol函数可以传入参数,参数只具有描述意义,没有什么本质的意义(仅仅用于区分)
let s=Symbol('1');
let s1=Symbol('2');
console.log(s);
console.log(s1);
二、set
ES6中新增了两种集合类型:set map
四种集合类型:数组 对象 set map
- 使用
通过new运算符来创建set集合 - 填充数据
- 通过构造函数
new set(数组); - 使用方法
add() 可以向set中添加数据,返回值依然为set(自身)
- 通过构造函数
- set的特点
set中只能保存不重复的数据 - set常见的属性和方法
- 属性:size 集合中数据的个数
- 方法:
add() 添加数据
delete() 删除数据
has(value) 判断集合中是否包含某数据 true/false
clear() 删除所有数据
- 遍历
可以使用forEach进行遍历
示例:使用set完成数组去重
//实现数组去重
let arr = [10, 20, 30, 10, 10, 20, 20, 100, 500];
// let s=new Set(arr);
// console.log(s);
let uniqArr = (arr) => {
// let s=new Set(arr);
// console.log(s);
// return [...s];//[]
return [...new Set(arr)];//先将数组转换为Set(完成了去重),在将set转换为数组
};
三、map
ES6中新增的集合结构
map其实是一种hash解构,数据由键值对组成 key/value
增强版的object,键可以使用任意类型
- 使用
new map(); - 属性方法
- 属性:size 集合中键值对的个数
- 方法:
set(key,value) 向map中添加数据
get(key) 从map中取出数据
has(key) 判断是否包含某元素 true/false
delete(key) 根据key删除元素
clear() 清除map
keys() 取出所有的键
values() 取出所有的值
entries() 实体
- 遍历
forEach
m.forEach((item,index) => {
console.log(item,index);
});
- map应用
转换为数组
let m=new Map();
m.set('name','张三');
let arr=[...m];
map–>对象
let m=new Map();
m.set('name','张三');
let obj={};
//for(let item of m){
// obj[item[0]]=item[1];
//}
for(let [key,value] of m){
obj[key]=value;
}
对象–>map
let obj={
name:'张三',
age:20
};
let m=new Map();
for(let item in obj){
m.set(item,obj[item]);
}
四、for…of遍历
for…of可以用来遍历set和map结构
for…of遍历产生的是值
let s = new Set([10, 20, 30, 100, 70]);
//for of遍历
for (let item of s) {
console.log(item);//10,20
}
let m = new Map();
m.set('name', '李四');
m.set('age', '20');
for (let item of m) {
console.log(item);//[name,李四][age,20]
}
for (let [key, value] of m) {
console.log(key, value);
}
iterator和generator
一、Iterator(遍历器、迭代器)
它可以为集合提供一种统一的接口机制,来遍历不同的集合数据。
//模拟Iterator机制(遍历器)
function makeIterator(array) {
var nextIndex = 0;//遍历过程中的索引
return {
next: function () {
if (nextIndex < array.length) {
return { value: array[nextIndex++], done: false };
}
return { value: undefined, done: true };
}
};
}
Iterator就是为了实现一种统一的接口机制,这种接口机制的表现形式即:for…of
一种数据结构只要部署了Iterator接口,就可以说它是可遍历的
Map、Set、数组结构都部署了该接口
对象类型并没有部署Iterator接口,所以,对象时不能使用for…of来进行遍历。若想使用for…of来对对象进行遍历,需要为对象部署iterator接口。
ES6规定,默认的Iterator接口部署在数据解构的Symbol.Iterator属性上。所以,一个数据结构只要具备了Symbol.Iterator属性,就认为是可遍历的。
// 我们以对象为例,来给对象部署默认iterator接口
let obj = { name: "zhangsan", age: 22, address: "北京" };
// 部署默认接口 Symbol.iterator ;用来访问不同的数据接口,真正实现iterator的功效
obj[Symbol.iterator] = function () {
let keys = Object.keys(this); //[name,age,address]
let index = 0; //记录索引下标
return {
// 箭头函数
next: () => {
if (index < keys.length) {
let key = keys[index++];
return { value: this[key], done: false };
} else {
return { value: undefined, done: true };
}
}
};
};
for…of相比forEach和for…in的优势在哪里:
1、无法中途跳出forEach循环,break命令或return命令都不能奏效。
2、数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。不安全
3、某些情况下,for…in循环会以任意顺序遍历键名。
总结:for…of适合遍历数组,for…in适合遍历对象
二、Generator(生成器)
Generator是一个函数。在function关键字和函数名直接添加*,这个时候,这个函数就变成了一个generator函数
Generator是一个状态机,内部封存了多个状态。直接调用generator函数并不会执行,而是会返回一个结果,iterator。
Generator函数经常来搭配yied表达式来使用,完成程序的分部执行。
function* show() {
yield console.log('111');
yield console.log('222');
yield console.log('333');
}
let i = show();//iterator迭代器
// console.log(i);
i.next();//执行第一个yied表达式
i.next();
i.next();
yied表达式没有返回值,若需要获取yied表达式后面的结果,则需要通过next方法来传递数据才可以。
function* show() {
let num = yield Math.pow(2, 2);
// console.log(num);//undefined
let n1 = yield Math.pow(num, 2);
console.log(n1);
}
let i = show();
// let obj=i.next();
// console.log(obj);
let { value } = i.next();
let { value: v1 } = i.next(value);
i.next(v1);