一道简单的算法题,重新认识字面量对象和Map

半腔热情 提交于 2020-04-29 15:22:53

场景:

如下,一道简单的算法题

解决思路如下, 遍历改变前的字符串,记录下每个字符对应出现的次数,然后遍历改变以后的字符串,依次将字符出现的次数减1,直到为0。 当新添加的字符被遍历到时,此时对应的次数已经为0,就可以检测到了。

    const map = new Map();
    for(let str of s) {
        const val = map.get(str);
        map.set(str, !val ? 1 : val + 1);
    }
    for(let str of t) {
        const val = map.get(str);
        if(!val) {
            return str;
        } else {
            map.set(str, val - 1);
        }
    }
复制代码

实不相瞒,看到结果我差点飘了。但这毕竟是一道很简单的题,所以并代表不了什么,还是想想如何优化吧, 不知道小伙伴们怎么看,我的第一反应是new Map()这一步占用了内存, 或许有更轻量的存储方式,比如 看似超级轻量 (不要被表面骗了) 的字面量对象

    // const map = new Map();
    const map = {}
复制代码

毕竟不用创建对象,应该会更节省空间吧, 于是我们更改代码如下

    const map = {};
    for (let i of s) {
        const val = map[i];
        map[i] = !val ? 1 : val + 1
    }

    for (let i of t) {
        const val = map[i];
        if (!val) {
            return i;
        }
        map[i]--;
    }
复制代码

自信满满地提交,然后

en?WTF!一夜回到解放前。。。

质疑:

  1. 为什么new一个对象反而比字面量对象更轻量,难道字面量对象的本质也是new Object()?

    因为之前看了本多博客,都讲的是创建字面量对象比直接创建对象要高效,毕竟不用直接new,所以首先质疑这一点,

    理论不如实践,我们直接测试:

        const obj_2 = new Object();
        const obj_3 = Object();
        const map = new Map();
        
        console.log("obj_1和obj_2的__proto__", obj_1.__proto__ === obj_2.__proto__);
        console.log("obj_1和obj_2的constructor", obj_1.constructor === obj_2.constructor);
        console.log("obj_1和obj_2的__proto__", obj_1.__proto__ === obj_3.__proto__);
        console.log("obj_1和obj_2的constructor", obj_1.constructor === obj_3.constructor);
    复制代码

    输出结果:

        obj_1和obj_2的__proto__ true
        obj_1和obj_2的constructor true
        obj_1和obj_2的__proto__ true
        obj_1和obj_2的constructor true
    复制代码

    我们知道,
    __proto__指向创建自己的那个构造函数的原型对象,
    constructor:指向创建自己的那个构造函数
    所以,可以下结论,三者皆是Object的实例。


  2. 同样是添加元素,为什么Map的效率高这么多(虽然只有10ms左右),难道Map内部采用了不同的存储或查找算法?

    这里看了两篇官网文章
    JavaScript 标准内置对象Map
    阮一峰老师 讲解的Iterator

结论:

  1. 字面量对象、new Object()和Object()三者创建出来的对象本质一样

  2. 创建Object的三种方式

    • 字面量对象
    • 构造方法创建
    • Object.create()
  3. 对象和Map各自擅长的应用场景

    • Object

      1. key只能是String 或是Symbol
      2. 场景中有json操作。目前json可直接与Object操作
    • Map

      1. 存储大量数据,尤其key的类型未知且key与value类型相同。key有可能为任意类型,包括函数,对象或任意基本类型
      2. 频繁对对象进行增删的场景。因为Map为hash结构。
      3. 频繁对变量迭代。Map可直接for...of或for...in,而Object需要先获取keys或values
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!