Set 集合,不同于 Array,是一种没有重复值的集合。

以下代码出自于《JavaScript 权威指南(第六版)》P217,注意:这里并不是指 es6 / es2015 中的 Set 集合。它只是提供了一种实现类的例子,因为代码写得很巧妙,我就想记录下来并分享给大家。

  1. // 定义一个 Set 构造函数
  2. function Set() {
  3. this.values = {}; // values 以键值对的形式表示集合的数据
  4. this.n = 0; // n 集合中值的个数
  5. // arguments 是实际参数的一个类数组对象
  6. // 保证在 new Set(1,'sarah',{}) 初始化构造函数时调用原型上的 add 方法,将传入的参数添加到集合中
  7. this.add.apply(this, arguments);
  8. }
  9.  
  10. // 将每个参数添加至集合中
  11. Set.prototype.add = function() {
  12. // 遍历每一个参数
  13. for (var i = 0; i < arguments.length; i++) {
  14. var val = arguments[i], // 值
  15. str = Set._v2s(val); // 键:通过值得到相应的键
  16. // 保证集合无重复值
  17. if (!this.values.hasOwnProperty(str)) {
  18. this.values[str] = val;
  19. this.n++; // 集合中值的计数加一
  20. }
  21. }
  22. return this; // 支持链式调用
  23. }
  24.  
  25. // 删除元素
  26. Set.prototype.remove = function() {
  27. // 遍历每一个参数
  28. for (var i = 0; i < arguments.length; i++) {
  29. var str = Set._v2s(arguments[i]); // 通过值得到相应的键
  30. if (this.values.hasOwnProperty(str)) { // 若 values 集合中存在该属性
  31. delete this.values[str]; // 删除元素
  32. this.n--; // 集合中值的计数减一
  33. }
  34. }
  35. return this; // 支持链式调用
  36. }
  37.  
  38. // 检测是否包含某个值
  39. Set.prototype.contains = function(value) {
  40. return this.values.hasOwnProperty(Set._v2s(value));
  41. }
  42.  
  43. // 返回集合的大小
  44. Set.prototype.size = function() {
  45. return this.n;
  46. }
  47.  
  48. // 遍历集合中的所有元素,在指定的上下文中调用回调函数 f
  49. Set.prototype.foreach = function(f, context) {
  50. for (var s in this.values) {
  51. if (this.values.hasOwnProperty(s)) {
  52. f.call(context, this.values[s]);
  53. }
  54. }
  55. }
  56.  
  57. // 在 Set 方法上定义一个自定义属性 _v2s
  58. // 该属性的值是一个方法,用于将传入的值转成对应的字符串(其实就像是打标签)
  59. Set._v2s = function(val) {
  60. switch (val) {
  61. case undefined: return 'u'; // 如果是 undefined,就返回 'u'
  62. case null: return 'n';
  63. case true: return 't';
  64. case false: return 'f';
  65. default: switch (typeof val) {
  66. case 'number': return '#' + val; // 如果是数字,就添加 # 前缀 ,例如 #123, #0.5
  67. case 'string': return '"' + val; // 如果是字符串,就添加 " 前缀 , 例如 "hello, "world
  68. default: return '@' + objectId(val); // 如果是数组、函数、对象等,就添加 @ 前缀,objectId 方法会返回一个特定数字,如:@100
  69. }
  70. }
  71.  
  72. function objectId(o) {
  73. var prop = "|**objectid**|"; // 给数组/ 函数/ 对象定义一个私有属性,用以存放 id
  74. if (!o.hasOwnProperty(prop)) { // 添加该属性前先判断该对象是否已经存在该属性
  75. o[prop] = Set._v2s.next++; // 不存在则添加该属性,值为 next
  76. }
  77. return o[prop];
  78. }
  79. }
  80. // 在 Set._v2s.next 方法上定义一个自定义属性 next,初始值为 100
  81. // 这样做的好处是,避免了全局变量污染,并且将该属性与对应的方法绑定在一起
  82. Set._v2s.next = 100;

以上代码就定义好了一个 Set 类,它可以向集合中添加元素,也可以删除元素,还可以查询某个元素是否在该集合中等等。下面我们就来测试一下:

  1. var arr = [3, 4, 5];
  2. var set = new Set(1, 1, 3, 'sarah', null, undefined, function () {}, arr, {});
  3. console.log(set);

打印 set,结果如下:

我在 new Set ( ) 的时候传入了 9 个参数,但打印结果中显示 n = 8,并且参数 1 只出现了一次,即 #1 。这说明了,set 集合不会添加重复值。

其它示例:

  1. var arr = [3, 4, 5];
  2. var set = new Set(1, 1, 3, 'sarah', null, undefined, function () {}, arr, {});
  3.  
  4. console.log(set.remove(null)); // n = 7
  5. console.log(set.contains('sarah')); // true
  6. console.log(set.contains('lissy')); // false
  7.  
  8. set.add([3, 4, 5]); // 可以成功,因为数组是引用类型,当前添加的这个 [3, 4, 5] 跟之前的 arr 不是指向同一个引用
  9. console.log(set.size()); //

我写这篇文章的目的不在于向大家提供 Set 这个构造函数,主要还是为了加深对类的理解。这其中在函数上定义自定义属性这一操作,是我在之前的代码中没有用到过的,它可以解决一些全局变量的问题,又可以和对应的函数紧密关联在一起,我觉得非常有用。

作者不才,文中若有错误,望请指正,避免误人子弟。

Set.js--创建无重复值的无序集合的更多相关文章

  1. MYSQL中防止插入重复记录的解决方案(无重复值更新)

    说明:一般我们使用MYSQL插入记录时,类似于这样的语句: insert into table_name(email,phone,user_id) values(‘test9@163.com’,’99 ...

  2. JS 数组去重复值

    var arr1 = [90, 91, 92]; var arr2 = [80, 81]; var arr3 = [80, 71, 72, 73]; var arr = arr1.concat(50, ...

  3. js 数组排除重复值(string)

    前提:数组中的元素类型为:string 在网上看了许多高大尚的文章,还是解决不了我的string arry 的问题,只能怪自己脑残了,上代码: <!DOCTYPE html> <ht ...

  4. js 创建List<Map> 这种格式的集合

    //赋值 var list_map = new Array(); for ( var i = 0; i < 10; i++) { list_map.push({baidux:'baidux'+i ...

  5. js中var的有或无--重复声明和以后的声明

    js中var的有或无--重复声明和以后的声明 使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误. 如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色. 如果重复 ...

  6. JS去除数组中重复值的四种方法

    JS去除数组中重复值的四种方法 1 /// <summary>            o[this[i]] = "";  }      }       newArr.p ...

  7. JS前端无侵入实现防止重复提交请求技术

    JS前端无侵入实现防止重复提交请求技术 最近在代码发布测试的过程中,我发现有些请求非常的消耗服务器资源,而系统测试人员因为响应太慢而不停的点击请求.我是很看不惯系统存在不顺眼的问题,做事喜欢精益求精, ...

  8. 【转】javascript中值传递,地址传递,引用传递的问题(使用js创建list对象时会用到)

    function initEditModal_SI(node) { if (node.siArray == undefined) { node.siArray = new Object(); } va ...

  9. JS两个数组比较,删除重复值巧妙方法

    //方法一 var arr1 = [1,2,3,4,5,6,7,8]; //数组A var arr2 = [1,2,3,11,12,13,14];//数组B var temp = []; //临时数组 ...

随机推荐

  1. [解决方案]SystemError: Parent module '' not loaded, cannot perform relative import的解决方案

    缺陷:__mian__不能使用相对导入 PEP 328 Relative Imports and __name__ 中说明: Relative imports use a module's __nam ...

  2. RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)

    在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...

  3. C# 绘制PDF图形——基本图形、自定义图形、色彩透明度

    引言 在PDF中我们可以通过C#程序代码来添加非常丰富的元素来呈现我们想要表达的内容,如绘制表格.文字,添加图形.图像等等.在本篇文章中,我将介绍如何在PDF中绘制图形,并设置图形属性的操作. 文章中 ...

  4. Docker 安装rabbitMQ

    Docker 安装rabbitMQ docker pull rabbitmq:3.7.7-management 使用:docker images 查看所有镜像 4.根据下载的镜像创建和启动容器 doc ...

  5. 解决Azure 消息队列ServiceBus提示证书不信任无权限的问题

    笔者在C# 消息队列-Microsoft Azure service bus 服务总线中使用Azure消息队列,最近偶尔会遇到请求数据不入队列的问题,查找日志,问题如下: 异常:X. certific ...

  6. Java Socket网络编程学习笔记(一)

    0.前言 其实大概半年前就已经看过网络编程Socket的知识了(传统IO),但是因为长时间的不使用导致忘的一干二净,最近正好准备校招,又重新看了网络编程这一章, 是传统IO(BIO)相关的内容,故在此 ...

  7. JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧

    这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...

  8. java servlet的执行流程

    1.先附上代码如下 Servlet1.java public class Servlet1 implements Servlet { @Override public void init(Servle ...

  9. 自然语言处理NLP快速入门

    自然语言处理NLP快速入门 https://mp.weixin.qq.com/s/J-vndnycZgwVrSlDCefHZA [导读]自然语言处理已经成为人工智能领域一个重要的分支,它研究能实现人与 ...

  10. Webpack4教程:第一部分,入口、输入和ES6模块

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://wanago.io/2018/07/16/webpack-4-course-par ...