ES6的Map、Set和ES7的Array.includes()、乘方

一、ES6

1.Set

1.Set的基本使用

  • 在ES6之前,我们存储数据的结构主要有两种:数组、对象。
  • 在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap

数据结构:存储数据的方式

  • Set是一个新增的数据结构,可以用来保存数据,类似于数组,但和数组最大的区别是 元素不能重复

    • 创建Set我们需要使用Set构造函数(暂时没有字面量创建的方式)
  • 应用场景

    • 添加的元素希望不重复
    • 给数组去重
      • new Set(arr)
      • 转化为数组
        • Array.from()
        • 展开运算符
// 10,20,40,333
// * 创建Set结构
let set=new Set();
// * 添加元素
set.add(10)
set.add(20)
set.add(40)
set.add(333)
set.add(10);//重复的元素会被忽略

// * 添加对象的注意点
set.add({});//两个对象是有不同的内存地址
set.add({});//和上面的{}的地址是不同的

const obj={name:"wjy"};
set.add(obj); 
set.add(obj); //*重复的内存地址也只会被添加一次
console.log(set);


// * 应用场景:①不想添加的元素重复  ② 给数组去重
const arr=[22,10,20,45,22,10,2];

// * 1.自己写的一个方法
const newArr=[];
for(const item of arr){
  if(newArr.indexOf(item)==-1){
    newArr.push(item)
  }
}
// * 可以使用Set
const arrSet=new Set(arr);
// * 方法1  Array.from
const newArr2=Array.from(arrSet);//* Array.from():对一个类似数组或可迭代对象创建一个新的、浅拷贝的数组实例
console.log(newArr2);
// * 方法2:展开运算符
const newArr3=[...arrSet];
console.log(newArr3);

2.Set常见的属性和方法

2.1 常见的属性
  • size:获取set的元素个数
console.log(set.size);
2.2 常见的方法
  • add(item):添加指定的元素,如果存在,则不添加
  • delete(item):删除指定的元素
  • has(item):判断指定的item是否在Set中
  • clear():清空Set集合
  • 遍历
    • forEach遍历
    • for...of
/**
 * * 常见的方法
 * * 1. add(item):添加指定元素
 * * 2. delete(item):删除指定元素
 * * 3.has(item):判断指定元素是否在Set中,如果有则返回true,否则返回false
 * * 4.clear():清空Set集合
 */

set.add("wjy");
console.log(set);
set.delete("wjy");
console.log(set);
console.log(set.has("wjy"));
set.forEach(item=>{
  console.log(item);
})

for(const item of set){
  console.log(item);
}
set.clear();
console.log(set);

2.WeakSet

和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。

  • 那么和Set有什么区别呢?
    • 区别一:WeakSet只能存放对象类型,不能存放基本数据类型
    • 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收。

强引用指的的是 指向的那条线是生效的。

弱引用指的是指向的那条线存在不存在,没有任何关系。

let obj={name:"why"};
let set=new Set();
set.add(obj);
console.log(set);
image-20220510185545267.png

如果将obj设置为null,set存储的元素也还是会被引用。

obj=null;
console.log(set);
image-20220510185619772.png

但如果是 WeakSet,因为WeakSet对元素的引用是弱引用,所以由weakSet指向那片地址其实没有用的,不算真正的引用,如果初略WeakSet本身实例指向那片地址,没有其他引用引用这个对象的话,这个对象会被GC回收掉。

const weakSet=new WeakSet();
let obj={name:"why"};
weakSet.add(obj);
image-20220510185836514.png
obj=null;

当obj不再引用这片地址空间时,没有其他引用引用了,除了weakSet本身的弱引用(但是这个弱引用是没有用的),这片内存空间会被GC回收掉。

image-20220510190221909.png

2.1 WeakSet的常用方法

  • add(item):添加某个元素,返回WeakSet对象本身
  • delete(item):从WeakSet中删除和这个值相等的元素,返回boolean类型
  • has(value):判断WeakSet中是否存在某个元素,返回boolean类型

注意:WeakSet不能遍历

  • 因为WeakSset只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁
  • 所以存储到WeakSet是没办法正常获取的。

2.2 应用场景

我们使用一个Stack Overflow上的答案:只能使用Person实例调用running,相对于Set比较方便,不需要手动是释放内存。

let weak=new WeakSet();
class Person{
  constructor(){
    weak.add(this);
  }
  running(){
    if(!weak.has(this)) throw new Error("Type Error ,NOT Person")
    console.log("running");
  }
}

const p=new Person();
p.running.call({name:'wjy'});

3.Map

另外一个新增的数据结构是Map,用于存储映射关系。

但是我们可能会想,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?

  • 事实上我们对象存储映射关系只能使用字符串(ES6中新增了Symbol)作为属性名(key)
  • 某些情况下我们可能希望通过其他类型作为key,比如key,这个时候会自动将对象转化为字符串来作为key
let obj1={name:"wjy"};
let obj2={name:"hyz"};

let o={
  [obj1]:'aaa',
  [obj2]:'bbb'
}

//* 因为对象后面被直接转换为 字符串[object Object],所以当同样的key被重复赋值时,只会保留最新的值。
//* []:这个是计算属性
console.log(o);//{ '[object Object]': 'bbb' }

那么我们就可以使用Map:

  • new Map() 创建一个Map实例对象
  • set(key,value)
// * Map允许对象作为key
let map=new Map();
let obj1={name:"wjy"};
let obj2={name:"hyz"};
map.set(obj1,"aaa");
map.set(obj2,"bbb")
map.set("name","wjy")
console.log(map);
// Map(3) {
//   { name: 'wjy' } => 'aaa',
//   { name: 'hyz' } => 'bbb',
//   'name' => 'wjy'
// }

let map2=new Map([[obj1,"aaa"],[obj2,"bbb"],["name","wjy"]]);//可以传入数组

console.log(map2);
// Map(3) {
//   { name: 'wjy' } => 'aaa',
//   { name: 'hyz' } => 'bbb',
//   'name' => 'wjy'
// }

3.1 常用的方法和属性

Map常见的属性:

  • size:返回Map的元素的个数

Map常用的方法:

  • set(key,value):在Map中添加key和value,并将整个Map对象返回。
  • get(key):根据key获取Map中的value。
  • has(key):判断是否包含某个key,返回Boolean类型。
  • delete(key):根据key删除一个键值对,返回Boolean类型。删除成功,返回true,删除失败,返回false
  • clear():清空map
  • 遍历
    • forEach((value,key)=>{})
    • for....of
      • 数组类型,第一个元素是key,第二个元素是value
/**
 * * 常用属性
 * * size:获取Map的元素个数
 */

console.log(map2.size);//3
/**
 * * 常用方法
 * * set:添加一个key和value,并将整个Map对象返回
 * * get:根据key获取Map中的value
 * * has:判断是否包含某个key,返回Boolean
 * * delete:根据key,删除键值对,删除成功返回true,删除失败返回false
 * * clear:清空
 */

console.log(map2.get(obj1));//aaa
console.log(map2.has("name"));//true
console.log(map2.delete("aa"));//false
map2.clear();
console.log(map2);//Map(0) {}

4.WeakMap

和Map类型相似的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。

那么和Map有什么区别呢?

  • WeakMap的key只能使用对象,不能使用基本数据类型
  • WeakMap的key对对象的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象。

Map是对key的强引用,WeakMap是对key的弱引用(这个引用是没有关系的)

let  obj1={name:"obj1"};
const map=new Map();
map.set(obj1,"aaaa");
image-20220510213359653.png
obj1=null

将obj1指向null,不指向那片内存空间,但是由于Map中对key的引用是强引用,所以并不会被回收掉的。

image-20220510213530774.png

但如果是WeakMap结果就是不一样的了。

let  obj1={name:"obj1"};
const map=new WeakMap();
map.set(obj1,"aaa");
image-20220510214123411.png
obj1=null;

将obj1指向null,不再指向那片空间,由于在weakMap中是弱引用,所以那片空间是可以被GC回收的。

image-20220510214717212.png

4.1 常见方法

  • set (key,value):向WeakMap中添加key,value值,并将整个WeakMap对象返回
  • get(key):根据key返回Map中的value
  • has(key):判断是否包含一个key,返回Boolean类型
  • delete(key):根据key删除一个键值对,返回Boolean类型

不能遍历

  • 没有forEach
  • 也不能使用for...of
let  obj1={name:"obj1"};
const map=new WeakMap();
map.set(obj1,"aaa");



/**
 * * 常见的方法
 * * set
 * * get
 * * delete
 * * has
 */
console.log(map.get(obj1));//aaa
console.log(map.has(obj1));//true
console.log(map.delete(obj1));//true

4.2 应用场景

  • Vue3响应式应用场景
let obj1={name:"wjy",age:20};
function obj1NameFn1(){
  console.log("obj1NameFn1被执行了");
}

function obj1NameFn2(){
  console.log("obj1NameFn2被执行了");
}

function obj1AgeFn1(){
  console.log("obj1AgeFn1被执行了");
}

function obj1AgeFn2(){
  console.log("obj1AgeFn2被执行了");
}


let obj2={
  name:"kobe",
  height:1.88,
  address:"广州市"
}

function obj2NameFn1(){
  console.log("obj2NameFn1被执行了");
}

function obj2NameFn2(){
  console.log("obj2NameFn2被执行了");
}
// 1. 创建一个WeakMap
let weakMap=new WeakMap();

// 2.1 收集依赖数据结构:对obj1收集的数据结构

const obj1Map=new Map();
obj1Map.set("name",[obj1NameFn1,obj1NameFn2]);
obj1Map.set("age",[obj1AgeFn1,obj1AgeFn2]);
weakMap.set(obj1,obj1Map)

// 2.2.收集依赖数据结构
const obj2Map=new Map();
obj2Map.set("name",[obj2NameFn1,obj2NameFn2]);
weakMap.set(obj2,obj2Map)

// 3 如果obj1.name发生了改变
// Proxy/Object.defineProperty
obj1.name="james";
const targetMap=weakMap.get(obj1);
const fns=targetMap.get("name");
fns.forEach(item=>item())

二、ES7

1.Array Includes

在ES7之前,如果我们想判断一个数组中是否包含某个元素,需要通过indexOf获取结果,并且判断是否为-1

在ES7之后,我们可以通过includes来判断一个数组中是否包含一个指定的元素,根据情况,如果包含则返回true,否则返回false

语法:

Array.includes(item,startIndex)
  • item:必需参数
  • startIndex:可选,从哪个位置开始查找
const names=["wjy","hyz","tl"];

if(names.indexOf("abc")!==-1){ //阅读性差
  console.log("包含");
}

// ES7 Array.includes():判断数组是否包含某个元素
// includes(item,startIndex); startIndex:从哪个位置开始判断
if(names.includes("wjy",0)){
  console.log("包含");
}

1.1 Array.includes和Array.indexOf的区别

如果数组中有个元素为NaN,

如果使用indexOf判断NaN是否存在,它会返回-1(找不到NaN这个元素)

如果使用includes判断NaN是否存在,它会返回true(找到了这个NaN元素)

const names=["wjy","hyz","tl",NaN];
if(names.indexOf(NaN)!==-1){  //* 即使数组中有NaN,但还是被判断为不存在
  console.log("包含NaN");
}

if(names.includes(NaN)){
  console.log("包含NaN");
}

2.指数(乘方运算)

在ES7之前,计算数字的乘方需要使用Math.pow方法来完成。

在ES7中,增加了**运算符,可以对数字来计算乘方。

// 计算3的3次方

// ES7之前
const result1=Math.pow(3,3);
// ES7后
const result2=3**3;

console.log(result1==result2);//true

三、总结

ES6的Set、WeakSet、Map、WeakMap和ES7的Array.includes和乘方.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容