ES6提供了新的数据结构SetSet对象不是数组, 可以用来保存对象或者基本类型, 所有保存的值都是唯一的, chrome浏览器>38和FF>13,以及nodeJS,对Set支持良好, 以下的一些代码,都可以拷贝到控制台直接运行哦;

  创建Set实例的基本方法为:

let set = new Set(); //或者 new Set(null);
console.log(set);

  或者这样:

let set = new Set([,,,,,,,]);
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) === - && obj!=undefined) {
__set.push(obj);
}
});
_this._set =__set;
this.size = _this._set.length;
}
constructor(arg) {
this.size = ;
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 = ;
return this;
}
delete (obj) {
if( this._set.indexOf(obj)!=- ) {
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)!=- ) 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 = ;
let val = undefined;
while(index<this.size) {
val = this._set[index];
yield val;
index++;
}
}
}
var set = new Set([,]);
//对Set进行基本的操作;
set.add().add().add().add({:})
set.delete();
set.add();
//使用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([,])).add()); // 输出:[1, 2, 3]
</script>

  

  clear方法,把set里面的数据清空;

let set = (new Set([,,,]));
set.clear();
Array.from(set);

  delete方法,删除set里面的指定数据:

let set = (new Set([,,,]));
set.delete();
Array.from(set); //输出:[2, 3, 4]

  entries方法:

let set = (new Set([,,,]));
Array.from(set.entries());

  forEach方法:set的forEach有两个参数, 第一个参数为一个函数,第二个参数是非必须的,如果传了第二个参数, 那么该函数的上下文this就是我们传的第二个参数:

<script>
let set = (new Set([,,,]));
set.forEach(function() {
console.log(arguments);
console.log(this)
},"");
</script>

  输出:

  

  has方法, has是判断这个set是否有指定的值, 返回false或者true;

<script>
let set = (new Set([,,,]));
console.log(set.has()) //输出:true;
console.log(set.has()) //输出:false
</script>

  keys方法和values()方法, 这两个方法都是返回一个迭代器;

<script>
let set = new Set([,,,]);
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([,,,]);
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();
mySet.add();
mySet.add("some text");
//添加对象
var o = {a: , b: };
mySet.add(o); mySet.has(); // 返回:true
mySet.has(); // 返回:false
mySet.has(); // 返回:true
mySet.has(Math.sqrt()); // 返回:true
mySet.has("Some Text".toLowerCase()); // t返回:rue
mySet.has(o); // 返回:true mySet.size; // mySet.delete(); // 从mySet里面删除5
mySet.has(); // 输出: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([,,,]), new Set([,,,]))); //输出:Set {2,3,4}

  弱引用的WeakSet

  WeakSet对象是一些对象值的集合, 并且其中的每个对象值都只能出现一次,WeakSet只能存对象类型的元素,比如:Object, Array, Function 等等;有了弱引用的WeakSet, 就不用担心内存泄漏了,如果别的对象不引用该对象, 这个对象会被垃圾回收机制自动回收;

<script>
console.log(new WeakSet([{},[],()=>({:})]));
</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);
},)
</script>

  weakSet可以用来保存DOM节点, 当节点被删除, weakSet里面的该节点如果不存在别的引用的话, 一段时间内会被内存回收;

  参考:

  MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

  ruanyifeng:http://es6.ruanyifeng.com/#docs/set-map

作者: NONO
出处:http://www.cnblogs.com/diligenceday/

QQ:287101329

微信:18101055830

ES6新特性:Javascript中Set和WeakSet类型的数据结构的更多相关文章

  1. javascript ES6 新特性之 扩展运算符 三个点 ...

    对于 ES6 新特性中的 ... 可以简单的理解为下面一句话就可以了: 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中. 作用类似于 Object.assign() ...

  2. ES6新特性概览

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  3. 你不知道的JavaScript--Item24 ES6新特性概览

    ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...

  4. ES6新特性概览1

    本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony( ...

  5. Atitit js版本es5 es6新特性

    Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...

  6. ES6新特性:Proxy代理器

    ES6新特性:Proxy: 要使用的话, 直接在浏览器中执行即可, node和babel目前还没有Proxy的polyfill;,要使用的话,直接在浏览器中运行就好了, 浏览器的兼容性为:chrome ...

  7. 必须掌握的ES6新特性

    ES6(ECMAScript2015)的出现,让前端开发者收到一份惊喜,它简洁的新语法.强大的新特性,带给我们更便捷和顺畅的编码体验,赞! 以下是ES6排名前十的最佳特性列表(排名不分先后): 1.D ...

  8. 前端入门21-JavaScript的ES6新特性

    声明 本篇内容全部摘自阮一峰的:ECMAScript 6 入门 阮一峰的这本书,我个人觉得写得挺好的,不管是描述方面,还是例子,都讲得挺通俗易懂,每个新特性基本都还会跟 ES5 旧标准做比较,说明为什 ...

  9. 34.js----JS 开发者必须知道的十个 ES6 新特性

    JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...

随机推荐

  1. Flex数据绑定陷阱(一)

    Flex数据绑定陷阱:常见的误用和错误 当构建Flex或者Adobe AIR程序时,将一个对象的值自动的传递给另一个对象这种处理是数据绑定最常 用并最有用的特征之一. 尽管如此,同时数据绑定会减缓程序 ...

  2. Maven学习(八)继承和聚合

    *聚合(多模块) 在一个项目中 往往有多个模块组成,例如有项目demo下面有a, b两个模块 为了能使用一条命令就能构建demo-a, demo-b两个模块, 需要创建一个额外的聚合模块, 然后通过该 ...

  3. JS获取当前页面的URL信息

    设置或获取对象指定的文件名或路径. <script> alert(window.location.pathname) </script> 设置或获取整个 URL 为字符串. & ...

  4. jenkins中通过git发版操作记录

    之前说到的jenkins自动化构建发版是通过svn方式,今天这里介绍下通过git方式发本的操作记录. 一.不管是通过svn发版还是git发版,都要首先下载svn或git插件.登陆jenkins,依次点 ...

  5. Apache配置中的ProxyPass 和 ProxyPassReverse

    apache中的mod_proxy模块用于url的转发,即具有代理的功能.应用此功能,可以很方便的实现同tomcat等应用服务器的整合,甚者可以很方便的实现web集群的功能. 例如使用apache作为 ...

  6. SQL Server对Xml字段的操作

    T-Sql操作Xml数据 一.前言 SQL Server 2005 引入了一种称为 XML 的本机数据类型.用户可以创建这样的表,它在关系列之外还有一个或多个 XML 类型的列:此外,还允许带有变量和 ...

  7. C# 如何定义让PropertyGrid控件显示[...]按钮,并且点击后以下拉框形式显示自定义控件编辑属性值

    关于PropertyGrid控件的详细用法请参考文献: 1.C# PropertyGrid控件应用心得 2.C#自定义PropertyGrid属性 首先定义一个要在下拉框显示的控件: using Sy ...

  8. Visual Studio2012打开时弹出“遇到异常:这可能是由某个扩展导致的”错误的解决办法

    Visual Studio2012打开时弹出"遇到异常:这可能是由某个扩展导致的"错误的解决办法: 具体问题如下: 分析原因:网上搜集了以下,出现异常的原因是安装了第三方控件,然后 ...

  9. rpc框架: thrift/avro/protobuf 之maven插件生成java类

    thrift.avro.probobuf 这几个rpc框架的基本思想都差不多,先定义IDL文件,然后由各自的编译器(或maven插件)生成目标语言的源代码,但是,根据idl生成源代码这件事,如果每次都 ...

  10. vtk renderer / rendering 绘制

    1.在绘制窗口中绘制出物体(静态的)vtkRenderWindow * w=vtkRenderWindow::New();  w->AddRenderer(r);        for(int ...