• home > webfront > ECMAS > javascript >

    再谈Object与Map的使用场景分析:性能对比分析

    Author:zhoulujun Date:

    Map和Object有非常多相似的地方需要我们去更深入的了解和对比,才能分析出他们分别更适合的应用场景。什么是MapMap是一种数据结构(它很特

    Map和Object有非常多相似的地方需要我们去更深入的了解和对比,才能分析出他们分别更适合的应用场景。

    Object与Map的异同及使用场景

    什么是Map

    Map是一种数据结构(它很特别,是一种抽象的数据结构类型),数据一对对进行存储,其中包含键以及映射到该键的值。并且由于键的唯一性,因此不存在重复的键值对。

    Map便是为了快速搜索和查找数据而生的

    例如:{(1, "smile"), (2, "cry"), (42, "happy")}

    在Map中,每一对数据的格式都为键值对的形式。

    注:Map中的键和值可以是任何数据类型,不仅限于字符串或整数


    什么是Object

    JavaScript中的常规对象是一种字典类型的数据结构——这意味着它依然遵循与Map类型相同键值对的存储结构

    Object中的key,或者我们可以称之为属性,同样是独一无二的并且对应着一个单独的value。

    另外,JavaScript中的Object拥有内置原型(prototype)。需要注意的是,JavaScript中几乎所有对象都是Object实例,包括Map。

    例如:{1: 'smile', 2: 'cry', 42: 'happy'}

    从定义上来看,Object和Map的本质都是以键值对的方式存储数据,但实质上他们之间存在很大的区别——

    • Object遵循普通的字典规则,键必须是单一类型,并且只能是整数、字符串或是Symbol类型。但在Map中,key可以为任意数据类型(Object, Array等)。(你可以尝试将一个对象设置为一个Object的key,看看最终的数据结构)

    • 元素顺序Map会保留所有元素的顺序,而Object并不会保证属性的顺序。(如有疑问可参考:链接)

    • 继承:Map是Object的实例对象,而Object显然不可能是Map的实例对象。

    var map = new Map([[1,2],[3,4]]);
    console.log(map instanceof Object); //true
    var obj = new Object();
    console.log(obj instanceof Map); //false


    Object和Map的应用场景

    Map相对于Object有很多优点,依然存在某些使用Object会更好的场景,毕竟Object是JavaScript中最基础的概念。

    • 如果你知道所有的key,它们都为字符串或整数(或是Symbol类型),你需要一个简单的结构去存储这些数据,Object是一个非常好的选择。构建一个Object并通过知道的特定key获取元素的性能要优于Map(字面量 vs 构造函数,直接获取 vs get()方法)

    • 如果需要在对象中保持自己独有的逻辑和属性,只能使用Object。

    • JSON直接支持Object,但尚未支持Map。因此,在某些我们必须使用JSON的情况下,应将Object视为首选。

    • Map是一个纯哈希结构,而Object不是(它拥有自己的内部逻辑)。使用delete对Object的属性进行删除操作存在很多性能问题。所以,针对于存在大量增删操作的场景,使用Map更合适

    • 不同于Object,Map会保留所有元素的顺序。Map结构是在基于可迭代的基础上构建的,所以如果考虑到元素迭代或顺序,使用Map更好,它能够确保在所有浏览器中的迭代性能

    • Map在存储大量数据的场景下表现更好,尤其是在key为未知状态,并且所有key和所有value分别为相同类型的情况下。


    Map和Object性能测试

    性能区别

    1. 当key为有序连续的整数时,Object的性能优于Map;(V8对Object在键为有序连续正整数时做了优化)

    2. 当key为字符串、非有序连续整数、Symbol时Map的 添加 和 读取 性能优于Object,修改 和 删除 操作性能相差不大;(Object会把键转为String类型,消耗了一部分性能)

    3. 当key为其他数据类型时,只能选择Map;(Object的键只能为string、symbol类型)

    其他区别

    1. Object可以通过多种方式(字面量、new Object()、Object.create()等)创建,其中字面量的方式方便快捷。Map只能通过构造函数方式创建;

    2. Map本身具有size属性,Object需要使用 keys()、values()等方法获取;

    3. Map本身具有可迭代属性,Object不具有;

    4. Map会保持数据的插入顺序,Object不会;


    chatGPT解释Object与Map性能

    具体测试代码:


    function createRandomKey() {
        return new Date().getTime().toString().substr(6, 7) + '-' + (Math.random() * 100000000).toString().substr(0, 7);
    }
    let keys = []
    function setKeys() {
        for (let i = 0; i < 1000000; i++) {
            keys.push(createRandomKey())
        }
    }
    setKeys()
    let obj = new Object()
    let map = new Map()
    function getObjectTimeDiff() {
        let t1 = new Date().getTime()
        for (let i in keys) {
            obj[keys[i]] = i
        }
        let t2 = new Date().getTime()
        for (let j in keys) {
            let value = obj[keys[j]]
        }
        let t3 = new Date().getTime()
        for (let k in keys) {
            obj[keys[k]] = keys[k]
        }
        let t4 = new Date().getTime()
        for (let l in keys) {
            delete obj[keys[l]]
        }
        let t5 = new Date().getTime()
        return `object 增:${t2 - t1},读:${t3 - t2},改:${t4 - t3},删:${t5 - t4}`
    }
    function getMapTimeDiff() {
        let t1 = new Date().getTime()
        for (let i in keys) {
            map.set(keys[i], i)
        }
        let t2 = new Date().getTime()
        for (let j in keys) {
            let value = map.get(keys[j])
        }
        let t3 = new Date().getTime()
        for (let k in keys) {
            map.set(keys[k], keys[k])
        }
        let t4 = new Date().getTime()
        for (let l in keys) {
            map.delete(keys[l])
        }
        let t5 = new Date().getTime()
        return `map 增:${t2 - t1},读:${t3 - t2},改:${t4 - t3},删:${t5 - t4}`
    }
    console.log(getObjectTimeDiff())
    console.log(getMapTimeDiff())

    再修改代码,将keys改为下标的的集合,测试key为连续的整数时

    function setKeys() {
        for (let i = 0; i < 1000000; i++) {
            keys.push(i)
        }
    }


    参考文章:

    【译】Object与Map的异同及使用场景 https://juejin.cn/post/6844903792094232584

    Map和Object性能测试https://juejin.cn/post/6992874755070099492




    转载本站文章《再谈Object与Map的使用场景分析:性能对比分析》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2023_0418_8940.html