网站首页 > 技术文章 正文
ES6和ES2015
其实很多同学分不大清楚,ES6和ES2015之间的区别,而且目前已经到了ES2022,笔者这里简单地做一个示意。
ES2015的全称是ECMAScript 2015,它表示的是ES6在2015年6月份发布的第一个版本,因此ES6是个历史性的名词,泛指5.1版本后的JavaScript的标准规范,ES2016,2017以及再后面的年份标志的版本都是ES6的范畴。
ECMAScript和JavaScript之间的关系,就是版本规范和具体实现之间的关系,虽然也有其他实现比如ActionScript等等,由于JavaScript实现使用占比广泛的原因,在一般的场合并不会特意去区分它们。
什么是Set
前面讲到了,ES6的第一个版本早在2015年就已经发布了,其中Map和Set就是其中比较常用的特性,以笔者这么些年的体会,其实很多同学都知道,尤其是有Java后端开发经验的同学,但是大家在实操中,使用Map和Set的情况比较不够。究其原因,还是理解不够深刻,并且JavaScript中使用Array和Object毕竟能满足绝大部分场景。
Set
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
Set对象是值的集合,可以按照插入的顺序进行迭代,Set中的值是唯一的。
这里讲下MDN中有个很有意思的描述,NaN和undefined是可以存入Set的,但在Set中NaN之间会被认为是重复值,但是NaN!==NaN
我们可以看到,实际的aSet中只有两个值。
Set比较常用的实例方法有add,clear,delete,entires,forEach,has,keys,values等,属性的话就是size,用来返回Set对象中值的个数。这里笔者就不一一进行演示了。我们拿一个大家可能经常会用到的场景来举例。
数组去重
// Use to remove duplicate elements from the array
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
求数组的并集、交集、补集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let u = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let i = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let d = new Set([...a].filter(x => !b.has(x)));
// Set {1}
WeakSet
仔细研读ES6规范的同学,相信还发现了WeakSet这么个内置对象,接下来我们来一起看看,它是什么,跟Set有什么区别
首先WeakSet对象是一些对象值的集合,并且其中的每个对象值只能出现一次。那就表示跟Set一样,值也是唯一的。
区别
- WeakSet只能存储对象,因此像基本类型就无法存入。
- WeakSet存储的是弱引用,那就意味着WeakSet中的对象,如果没有其他引用,垃圾回收机制会自动该对象所占用的内存。
实例1
基于弱引用的特点,我们有没有具体使用的场景呢?WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
那我们思考下,比如DOM对象的使用,我们打开下百度页面,有个元素Id是s_fm
const a=new WeakSet();
//undefined
a.add(document.getElementById('s_fm'));
//WeakSet {div#s_fm.s_form.s_form_login}
a.has(document.getElementById('s_fm'))
//true
我们向a这个WeakSet中添加这个dom的引用,然后使用has实例方法判断下,这个引用是存在的。
然后我们把这个元素从DOM树上删除,然后再试一下
document.getElementById('s_fm').remove();
//undefined
a.has(document.getElementById('s_fm'))
//false
实例2
再来个MDN上的例子,检测循环引用
递归调用自身的函数需要一种通过跟踪哪些对象已被处理,来应对循环数据结构的方法。
为此,WeakSet非常适合处理这种情况
// 对 传入的subject对象 内部存储的所有内容执行回调
function execRecursively(fn, subject, _refs = null){
if(!_refs)
_refs = new WeakSet();
// 避免无限递归
if(_refs.has(subject))
return;
fn(subject);
if("object" === typeof subject){
_refs.add(subject);
for(let key in subject)
execRecursively(fn, subject[key], _refs);
}
}
const foo = {
foo: "Foo",
bar: {
bar: "Bar"
}
};
foo.bar.baz = foo; // 循环引用!
execRecursively(obj => console.log(obj), foo);
在此,在第一次运行时创建WeakSet,并将其与每个后续函数调用一起传递(使用内部参数_refs)。 对象的数量或它们的遍历顺序无关紧要,因此,WeakSet比Set更适合(和执行)跟踪对象引用,尤其是在涉及大量对象时。
好了,今天的分享就到这里,这个系列的下一期我们聊下还有个被大家遗忘的Map。
大家喜欢的话可以点个关注哦,或者关注下公众号:喵爸的小作坊
- 上一篇: 8个常用的JavaScript数组方法
- 下一篇: 你好 五月
猜你喜欢
- 2024-11-23 8个常用的JavaScript数组方法
- 2024-11-23 「JavaScript 从入门到精通」19.相等性判断
- 2024-11-23 Proxy 来代理 JavaScript 里的类
- 2024-11-23 前端笔记-js浅拷贝和深拷贝
- 2024-11-23 DOM 高级工程师不完全指南
- 2024-11-23 软件定义存储之ScaleIO、命令行操作和常用API使用指南
- 2024-11-23 Javascript的JSON.stringify()知多少?
- 2024-11-23 推荐10个“不能错过”的前端攻城师必背面试题源码及详解
- 2024-11-23 Web 前端怎样入门?
- 2024-11-23 JavaScript优化技巧
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-