zoukankan      html  css  js  c++  java
  • JavaScript学习笔记-自定义集合类

    //集合类Set( ES6标准才有的类,目前兼容性较差)
    //自定义集合类:
    extend = function (o,p){ //定义一个复制对象属性的类函数
    for(var x in p){ o[x] = p[x]; }
    return o;
    };
    function Set(){
    this.values = {};
    this.n = 0;
    this.add.apply(this,arguments); //把所有参数都添加进这个集合
    }
    Set.prototype.add = function(){ //定义添加方法
    for(var i = 0;i<arguments.length;i++){
    var val = arguments[i];
    var str = Set._v2s(val);
    if(!this.values.hasOwnProperty(str)){ //判断是否在集合中
    this.values[str] = val; //按字符串和值对添加进集合
    this.n++; //集合中的值+1
    }
    }
    return this; //支持链式调用
    };
    Set.prototype.remove = function(){ //定义删除方法
    for(var i = 0;i<arguments.length;i++){
    var str = Set._v2s(arguments[i]);
    if(this.values.hasOwnProperty(str)){
    delete this.values[str];
    this.n--;
    }
    }return this;
    };
    Set.prototype.contains = function(value){
    return this.values.hasOwnProperty(Set._v2s(value));
    };
    Set.prototype.size = function(){ return this.n;};
    //遍历集合中的所有元素,在指定的上下文context中对每个元素执行函数f
    Set.prototype.foreach = function(f,context){
    for(var s in this.values){
    if(this.values.hasOwnProperty(s)){
    f.call(context,this.values[s]);
    }
    }
    };

    //作用:对任意对象都返回一个字符串,针对不同对象返回不同的字符串,对于同一对象返回相同字符串
    Set._v2s = function(val){
    switch (val){
    case undefined:return 'u';
    case null: return 'n';
    case true: return 't';
    case false: return 'f';
    default :switch (typeof val){
    case 'number': return '#'+val;
    case 'string': return '"'+val;
    default :return '@'+objectId(val);
    }
    }
    //给对象o创建一个不可枚举且只读的属性,用来存放id
    function objectId(o){
    var prop = '|**objectid**|';
    if(!o.hasOwnProperty(prop)) o[prop] = Set._v2s.next++;
    return o[prop];
    }
    };
    Set._v2s.next = 100;
    //==类工厂,子类,父类===
    function fromSubclass(superclass,f){
    var c = function(){
    superclass.apply(this,arguments); //调用父类的构造函数
    };
    var proto = c.prototype =Object.create(superclass.prototype);
    proto.constructor = c;
    proto.add = function(){
    for(var i=0;i<arguments.length;i++){
    var v=arguments[i];
    if(!f(v)) throw ('value'+v+'!');
    }
    superclass.prototype.add.apply(this,arguments); //调用父类的原型方法
    };
    return c;
    }
    var f1 = function(x){return typeof x === 'string';};
    var f2 = function(x){return typeof x === 'function';};
    var StringSet = fromSubclass(Set,f1); //可以很方便的根据不同的父类来创建子类,只需改一下参数即可
    var MySet = fromSubclass(Set,f2);
    //===定义并立即调用
    var NonNullSet = (function(){
    var superclass = Set; //只需改此值,就可以继承自不同的父类
    return extend(
    function(){ superclass.apply(this,arguments)}, //构造函数指代类本身
    {
    add:function () {
    for (var i = 0; i < arguments.length; i++) {
    if (arguments[i] == null) {
    throw new Error('can not add null or undefined');
    }
    }
    return superclass.prototype.add.apply(this, arguments);
    }
    }
    );
    }());
    //======='组合优于继承': 使用组合代替继承========================================
    //只需创建一个单独的ChildClass子类,利用这个类的实例来创建继承自不同的superClass和执行不同的func方法
    var ChildClass = extend(
    function ChildClass(superClass,func){
    this.set = superClass;
    this.filter = func;
    },
    {
    add:function(){
    if(this.filter){
    for(var i = 0;i<arguments.length;i++){
    var v = arguments[i];
    if(!this.filter(v)){
    throw new Error('ChildClass:value '+v+'null');
    }
    }
    this.set.add.apply((this.set,arguments));
    return this;
    }
    },
    remove:function(){
    this.set.remove.apply(this.set,arguments);
    return this;
    },
    contains:function(v){return this.set.contains(v);},
    size:function(){return this.set.size();},
    foreach:function(f,c){this.set.foreach(f,c);}
    }
    );
    //==
    var s = new ChildClass(new Set(),function(x){return x!== null;});
    var t = new ChildClass(s,function(x){return !(x instanceof Set);});
    //=======抽象类和非抽象类的层次结构========================================
    // 抽象方法
    function abstractmethod() { throw new Error("abstract method"); }
    //抽象类
    function AbstractSet() { throw new Error("Can't instantiate abstract classes");}
    AbstractSet.prototype.contains = abstractmethod; //抽象方法contains

    var AbstractWritableSet = extend(
    function() { throw new Error("Can't instantiate abstract classes"); },
    {
    add: abstractmethod,
    remove: abstractmethod,
    union: function(that) {
    var self = this;
    that.foreach(function(v) { self.add(v); });
    return this;
    },
    intersection: function(that) {
    var self = this;
    this.foreach(function(v) { if (!that.contains(v)) self.remove(v);});
    return this;
    },
    difference: function(that) {
    var self = this;
    that.foreach(function(v) { self.remove(v); });
    return this;
    }
    });
  • 相关阅读:
    CMD指令
    六种Socket I/O模型幽默讲解
    性格与职业的选择
    为什么主引导记录的内存地址是0x7C00?
    pandas数据分析第二天
    pandas数据结构和介绍第一天
    tornado options
    tornado.web.StaticFileHandler
    mysql多条更新
    pandas
  • 原文地址:https://www.cnblogs.com/susufufu/p/5705777.html
Copyright © 2011-2022 走看看