ES6新特性-JavaScript中Set和WeakSet类型的数据结构的代码详细介绍
ES6提供了新的数据结构Set,Set对象不是数组, 可以用来保存对象或者基本类型, 所有保存的值都是唯一的, chrome浏览器>38和FF>13,以及nodeJS,对Set支持良好, 以下的一些代码,都可以拷贝到控制台直接运行哦;
创建Set实例的基本方法为:
let set = new Set(); //或者 new Set(null); console.log(set);
或者这样:
let set = new Set([1,2,3,4,4,4,4,4]); console.log( Array.from(set) ); //输出:[ 1, 2, 3, 4 ]
可以看到,以上重复的4,在set里面只保存了一个, 所以Set对象可以用来给数组去重;
Set也能用来保存NaN和undefined, 如果有重复的NaN, Set会认为就一个NaN(实际上NaN!=NaN);
实例Set以后的对象拥有这些属性和方法:
属性
Set.prototype
Set.prototype.size
方法
Set.prototype.add()
Set.prototype.clear()
Set.prototype.delete()
Set.prototype.entries()
Set.prototype.forEach()
Set.prototype.has()
Set.prototype.values()
Set.prototype[@@iterator]()
Set这种类型的数据结构其实我们可以直接用数组模拟出来, 虽然不能和原生的比, 只能模拟以上列表的一些方法和属性( 还有一些功能无法实现的 , Set实例的[Symbol.species]指向自己, 但是chrome中没有[Symbol.species]这个玩意儿…. )
使用数组模拟一个Set构造器:
<html> <head> <meta charset="utf-8"> </head> <body> <script> "use strict"; class Set { //对_set进行去重; static refresh () { let _this = this; let __set = [] this._set.forEach(function(obj) { if( __set.indexOf(obj) === -1 && obj!=undefined) { __set.push(obj); } }); _this._set =__set; this.size = _this._set.length; } constructor(arg) { this.size = 0; this[Symbol.species] = this; this._set = Array.isArray(arg)&&arg||[]; Set.refresh.call(this) } add (obj) { this._set.push(obj); Set.refresh.call(this) return this; } clear () { this._set.length = 0; return this; } delete (obj) { if( this._set.indexOf(obj)!=-1 ) { this._set[this._set.indexOf(obj)] = undefined; }; Set.refresh.call(this); return this; } /** * @desc * @return Entries [[],[],[],[]] * */ entries () { let result = []; this.forEach(function(key, value) { result.push([key,value]); }); return result; } has () { if( this._set.indexOf(obj)!=-1 ) return true; } keys () { return this[Symbol.iterator](); } values () { return this[Symbol.iterator](); } //直接使用数组的forEach方便啊; forEach (fn, context) { let _this = this; this._set.forEach((value) => fn.call(context||value, value, value, _this) ); } //必须支持生成器的写法; *[Symbol.iterator] (){ let index = 0; let val = undefined; while(index<this.size) { val = this._set[index]; yield val; index++; } } } var set = new Set([0,0]); //对Set进行基本的操作; set.add(1).add(2).add(3).add({1:1}) set.delete(1); set.add(1); //使用Set的forEach方法; set.forEach(function(key,value,s){console.log(key,value,s,"this")},{this:"this"}) //检测生成器是否正常运行; for(let s of set) { console.log(s) } //因为这个对象有Symbol.iterator, 所以使用扩展符也是好使的; console.log([...set]); </script> </body> </html>
Set实例的属性:
size属性:size是指这个Set的长度,和数组的length效果一样的”
constructor属性: 这个属性指向Set构造函数 ,这个代码即可实现 (new Set).constructor === Set //输出:true
Set实例的方法:
add方法,往set添加数据;
<script> Array.from((new Set([1,2])).add(3)); // 输出:[1, 2, 3] </script>
clear方法,把set里面的数据清空;
let set = (new Set([1,2,3,4])); set.clear(); Array.from(set);
delete方法,删除set里面的指定数据:
let set = (new Set([1,2,3,4])); set.delete(1); Array.from(set); //输出:[2, 3, 4]
entries方法:
let set = (new Set([1,2,3,4])); Array.from(set.entries());
forEach方法:set的forEach有两个参数, 第一个参数为一个函数,第二个参数是非必须的,如果传了第二个参数, 那么该函数的上下文this就是我们传的第二个参数:
<script> let set = (new Set([1,2,3,4])); set.forEach(function() { console.log(arguments); console.log(this) },"1111"); </script>
输出:
has方法, has是判断这个set是否有指定的值, 返回false或者true;
<script> let set = (new Set([1,2,3,4])); console.log(set.has(1)) //输出:true; console.log(set.has(5)) //输出:false </script>
keys方法和values()方法, 这两个方法都是返回一个迭代器;
<script> let set = new Set([1,2,3,4]); console.log(set.keys()); console.log(set.values()); var keys = set.keys(); for(let key of keys) { console.log(key); }; </script>
@@iterator()方法, @iterator方法是set默认的迭代器;
<script> let set = new Set([1,2,3,4]); let setIner = set[Symbol.iterator](); console.log(setIner.next().value) //输出:1 console.log(setIner.next().value) //输出:2 console.log(setIner.next().value) //输出:3 console.log(setIner.next().value) //输出:4 </script>
实际上我们可以重写set[Symbol.iterator],但是不会对set的keys和values方法产生影响;
整个DEMO:
var mySet = new Set(); //往mySet里面添加数据, 1 , 5 mySet.add(1); mySet.add(5); mySet.add("some text"); //添加对象 var o = {a: 1, b: 2}; mySet.add(o); mySet.has(1); // 返回:true mySet.has(3); // 返回:false mySet.has(5); // 返回:true mySet.has(Math.sqrt(25)); // 返回:true mySet.has("Some Text".toLowerCase()); // t返回:rue mySet.has(o); // 返回:true mySet.size; // 4 mySet.delete(5); // 从mySet里面删除5 mySet.has(5); // 输出:false, 5 已经被删除了 mySet.size; // 现在的长度为:3 // 通过 for...or循环获取数据; // 输出: 1, "some text" for (let item of mySet) console.log(item); // 输出: 1, "some text" for (let item of mySet.keys()) console.log(item); // 输出: 1, "some text" for (let item of mySet.values()) console.log(item); // 输出: 1, "some text", 对于Set来说:key和value是一样的 for (let [key, value] of mySet.entries()) console.log(key); // 把迭代器转化为数组的第一种方式; var myArr = [v for (v of mySet)]; // [1, "some text"] // 把迭代器转化为数组的第二种方式; var myArr = Array.from(mySet); // [1, "some text"] // 也可以用next()方法,手动去获取每一个值;
Set的实际用处:
利用set可以方便的进行交集和并集:
求并集, 我们可以给两个方案或者更多:
var union = (setA, setB) => { //[...setA]这种方式目前只有babel才支持 return new Seet([...setA,...setB]); }; var union = (setA, setB) => { return new Set(Array.from(setA).concat(Array.from(setB))); }
这种获取交集的方式,和数组求交集差不多;
var intersect = (set1, set2) => { //return [x for (x of set1) if (set2.has(x))]; 这种写法完全不行嘛.... var resultSet = new Set(); for(let set of set1) { if(set2.has(set)) { resultSet.add(set); }; }; return resultSet; };
以下这种代码更短,太酷了啊, 这个方法来自:http://es6.ruanyifeng.com/#docs/set-map;
var intersect = (set1, set2) => { return new Set([...set1].filter(x => set2.has(x))); } console.log(intersect(new Set([1,2,3,4]), new Set([2,3,4,5]))); //输出:Set {2,3,4}
弱引用的WeakSet
WeakSet对象是一些对象值的集合, 并且其中的每个对象值都只能出现一次,WeakSet只能存对象类型的元素,比如:Object, Array, Function 等等;有了弱引用的WeakSet, 就不用担心内存泄漏了,如果别的对象不引用该对象, 这个对象会被垃圾回收机制自动回收;
<script> console.log(new WeakSet([{},[],()=>({1:1})])); </script>
WeakSet对象的方法只有三个,而且WeakSet对象没有size属性;
weakSet.add();
weakSet.delete();
weakSet.has();
如果对象不存在引用, 那么WeakSet对象会把没有引用的对象占用的内存回收, 下面这个demo,你可以跑一下, 然后过一会儿(我的chrome浏览器10S就看到效果了)再看控制台:
<script> var ws = new WeakSet() var obj = {}; ws.add(obj); ws.add([]) setInterval(()=>{ console.log(ws); },1000) </script>
weakSet可以用来保存DOM节点, 当节点被删除, weakSet里面的该节点如果不存在别的引用的话, 一段时间内会被内存回收;
以上就是ES6新特性-JavaScript中Set和WeakSet类型的数据结构的代码详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务
