• ES6新特性:Javascript中的Map和WeakMap对象


      Map对象

      Map对象是一种有对应 键/值 对的对象, JS的Object也是 键/值 对的对象 ;

      ES6中Map相对于Object对象有几个区别:

      1:Object对象有原型, 也就是说他有默认的key值在对象上面, 除非我们使用Object.create(null)创建一个没有原型的对象;
      2:在Object对象中, 只能把String和Symbol作为key值, 但是在Map中,key值可以是任何基本类型(String, Number, Boolean, undefined, NaN....),或者对象(Map, Set, Object, Function , Symbol , null....);
      3:通过Map中的size属性, 可以很方便地获取到Map长度, 要获取Object的长度, 你只能用别的方法了;
      Map实例对象的key值可以为一个数组或者一个对象,或者一个函数,比较随意 ,而且Map对象实例中数据的排序是根据用户push的顺序进行排序的, 而Object实例中key,value的顺序就是有些规律了, (他们会先排数字开头的key值,然后才是字符串开头的key值);

      Map实例的属性  

      map.size这个属性和数组的length是一个意思,表示当前实例的长度;

      Map实例的方法

      clear()方法, 删除所有的键/值对;
      delete(key), 删除指定的键/值对;
      entries()返回一个迭代器, 迭代器按照对象的插入顺序返回[key, value];
      forEach(callback , context) 循环执行函数并把键/值对作为参数; context为执行函数的上下文this;
      get(key) 返回Map对象key相对应的value值;
      has(key) 返回布尔值, 其实就是返回Map对象是否有指定的key;
      keys() 返回一个迭代器,迭代器按照插入的顺序返回每一个key元素;
      set(key, value) 给Map对象设置key/value 键/值对, 返回这个Map对象(相对于Javascript的Set,Set对象添加元素的方法叫做add,而Map对象添加元素的方法为set;
      [@@iterator] 和entrieds()方法一样, 返回一个迭代器, 迭代器按照对象的插入顺序返回[key, value];

      自己模拟一个Map构造器:

      既然知道了Map对象的方法和属性, 我们也可以自己模拟一个Map构造器, 需要生成器的支持, 所以要在ES5中使用还需要生成器的补丁(模拟Set构造器) :

    <html>
    <head>
        <meta charMap="utf-8">
    </head>
    <body>
        <script>
            "use strict";
            class Map {
                /**
                 * @param [[key, value], [k, val]];
                 * @return void;
                 */
                static refresh (arg) {
                    for(let [key,value] of arg) {
                        //判断是否重复了;
                        let index = Map.has.call(this, key);
                        if(index===false) {
                            this._keys.push(key);
                            this._values.push(value);
                        }else{
                            //如果有重复的值,那么我们执行覆盖;
                            this._keys[index] = key;
                            this._values[index] = value;
                        }
                    };
                    this.size = this._keys.length;
                }
                /**
                 * @desc return false || Number;
                 * */
                static has (key) {
                    var index = this._keys.indexOf(key);
                    if(index === -1) {
                        return false;
                    }else{
                        return index;
                    };
                }
                constructor(arg) {
                    this._keys = [];
                    this._values = [];
                    Map.refresh.call(this, arg);
                }
                set (key, value) {
                    Map.refresh.call(this, [[key,value]]);
                    return this;
                }
                clear () {
                    this._keys = [];
                    this._values = [];
                    return this;
                }
                delete (key) {
                    var index = Map.has.call(this, key);
                    if(index!==false) {
                        this._keys.splice(index,1);
                        this._values.splice(index,1);
                    };
                    return this;
                }
                entries () {
                    return this[Symbol.iterator]();
                }
                has (key) {
                    return Map.has.call(this, key) === false ? false : true;
                }
                *keys() {
                    for(let k of this._keys) {
                        yield k;
                    }
                }
                *values () {
                    for(let v of this._values) {
                        yield v;
                    }
                }
                //直接使用数组的forEach方便啊;
                forEach (fn, context) {
                    return this;
                }
                //必须支持生成器的写法;
                *[Symbol.iterator] (){
                    for(var i=0; i<this._keys.length; i++) {
                        yield [this._keys[i], this._values[i]];
                    }
                }
            };
            var map  = new Map([["key","value"]]);
            map.set("heeh","dada");
            console.log(map.has("key")); //输出:true;
            map.delete("key");
            console.log(map.has("key"));  //输出:false;
            map.set("key","value");
            var keys = map.keys();
            var values = map.values();
            console.log(keys.next());
            console.log(keys.next());
            console.log(values.next());
            console.log(values.next());
            var entries = map.entries();
            console.log(entries);
        </script>
    </body>
    </html>
    View Code

      Map的使用Demo:

    var myMap = new Map();
    
    var keyString = "a string",
        keyObj = {},
        keyFunc = function () {};
    
    // 我们给myMap设置值
    myMap.set(keyString, "字符串'");
    myMap.set(keyObj, "对象");
    myMap.set(keyFunc, "函数");
    
    myMap.size; // 输出长度: 3
    
    // 获取值
    console.log(myMap.get(keyString));    // 输出:字符串
    console.log(myMap.get(keyObj));       // 输出:对象
    console.log(myMap.get(keyFunc));      // 输出:函数
    
    console.log(myMap.get("a string"));   // 输出:字符串
    
    console.log(myMap.get({}));           // 输出:undefined
    console.log(myMap.get(function() {})) // 输出:undefined

      我们也可以把NaN,undefined, 对象,数组,函数等这些作为一个Map对象的key值 :

    "use strict";
    let map = new Map();
    map.set(undefined, "0");
    map.set(NaN, {});
    console.log(map); //输出:Map { undefined => '0', NaN => {} }

      循环Map的方法

      使用Map实例的forEach方法;

    "use strict";
    let map = new Map();
    map.set(undefined, "0");
    map.set(NaN, {});
    map.forEach(function(value ,key ,map) {
        console.log(key,value, map);
    });

      使用for...of循环:

    "use strict";
    let map = new Map();
    map.set(undefined, "0");
    map.set(NaN, {});
    for(let [key, value] of map) {
        console.log(key, value);
    }
    for(let arr of map) {
        console.log(arr);
    }

      WeakMap

      WeakMap是弱引用的Map对象, 如果对象在js执行环境中不存在引用的话,相对应的WeakMap对象内的该对象也会被js执行环境回收;

      WeakMap对象的属性:无

      WeakMap对象的方法:

      delete(key) : 删除指定的键/值对;

      get(key) :返回Map对象key相对应的value值;

      has(key) :返回布尔值, 其实就是返回Map对象是否有指定的key;

      set(key):给Map对象设置key/value 键/值对, 返回这个Map对象;

      WeakMap相对于Map少了很多的方法, 我们也可以自己再来实现这些方法,比如我们再实现一个Map实例的clear方法:

    class ClearableWeakMap {
      constructor(init) {
        this._wm = new WeakMap(init)
      }
      clear() {
        this._wm = new WeakMap()
      }
      delete(k) {
        return this._wm.delete(k)
      }
      get(k) {
        return this._wm.get(k)
      }
      has(k) {
        return this._wm.has(k)
      }
      set(k, v) {
        this._wm.set(k, v)
        return this
      }
    }

      

      参考:

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

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

    作者: NONO
    出处:http://www.cnblogs.com/diligenceday/
    QQ:287101329
    微信:18101055830 

  • 相关阅读:
    反向传播BP算法
    有关一些求导的概念与神经网络梯度下降
    CS224n学习笔记(二)
    CS224n学习笔记(一)
    【模板】动态主席树
    【模板】静态主席树
    【模板】替罪羊树
    【模板】Splay
    洛谷 2387/BZOJ 3669 魔法森林
    洛谷 2622 关灯问题Ⅱ
  • 原文地址:https://www.cnblogs.com/diligenceday/p/5484130.html
Copyright © 2020-2023  润新知