【问题标题】:How is a JavaScript hash map implemented?JavaScript 哈希映射是如何实现的?
【发布时间】:2012-02-11 06:08:24
【问题描述】:

我目前使用 OpenLayers,并且有大量数据要绘制到矢量图层(超过 100000 个矢量)。

我现在正尝试将所有这些向量放入 JavaScript 哈希映射中以分析性能。我想知道JavaScript中的hash map是如何实现的,是真正的hash函数还是只是一个使用简单数据结构和搜索算法的包装函数?

【问题讨论】:

  • JS实现不止一种,所以没办法回答。 ECMAScript 没有指定对象使用什么数据结构,也没有指定访问时间的限制。散列是典型的,但可以使用平衡树。
  • ES6 有纯 Maps。该链接描述了普通对象和 Map 之间的区别、关键细节等:MDN JavaScript Map

标签: javascript hash hashmap


【解决方案1】:

每个 javascript object 都是一个简单的 hashmap,它接受字符串或 Symbol 作为其键,因此您可以将代码编写为:

var map = {};
// add a item
map[key1] = value1;
// or remove it
delete map[key1];
// or determine whether a key exists
key1 in map;

javascript对象在其实现上是一个真正的hashmap,所以搜索的复杂度是O(1),但是对于javascript字符串没有专门的hashcode()函数,它是由javascript引擎内部实现的(V8,SpiderMonkey,JScript .dll等...)

2020 年更新:

现在的javascript 也支持其他数据类型:MapWeakMap。与传统对象相比,它们的行为更接近于哈希映射。

【讨论】:

  • 完美。我之前使用过 $('div#someDiv').data(key, value) ,这个更简单,并且可能对旧浏览器也有更好的支持。谢谢
  • 有没有办法找到地图的长度?
  • @Sridhar 使用 Object.keys(map).length
  • 请注意,您可以使用数字作为键 map[2] = 'foo',但它会在内部转换为字符串 > map = { '2': 'foo' }
  • @otakustay 这是我今天才知道的超酷功能 :) 真的我需要密切学习 Javascript。
【解决方案2】:

这是一种使用类似于 Java map 的简单方便的方法:

var map= {
    'map_name_1': map_value_1,
    'map_name_2': map_value_2,
    'map_name_3': map_value_3,
    'map_name_4': map_value_4
    }

并获得价值:

alert( map['map_name_1'] );    // fives the value of map_value_1

......  etc  .....

【讨论】:

    【解决方案3】:

    JavaScript 对象不能纯粹在哈希映射之上实现。

    在您的浏览器控制台中试试这个:

    var foo = {
        a: true,
        b: true,
        z: true,
        c: true
    }
    
    for (var i in foo) {
        console.log(i);
    }
    

    ...您会按照插入顺序收到它们,即de facto standard 行为。

    哈希映射本质上不维护顺序,因此 JavaScript 实现可能以某种方式使用哈希映射,但如果这样做,它至少需要一个单独的索引和一些额外的插入簿记。

    这是Lars Bak explaining why v8 doesn't use hash maps to implement objects的视频。

    【讨论】:

    • "otakustay 在技术上是错误的,是最糟糕的错误。"这有点苛刻。它可能不是 1:1,但出于使用像字典这样的哈希的意图和目的,它以相同的方式工作。
    • 只是想澄清一下,这对于 JavaScript 的某些实现(例如大多数浏览器)可能是正确的,但不一定总是正确的。键的迭代顺序不是由 ECMAScript 标准定义的,可以是任何顺序,但仍然是有效的 JS 实现。
    • 与某些实现是否使用散列的问题不同,它们是否还保留插入顺序的键列表以方便用户使用与原始问题无关。
    【解决方案4】:
    <html>
    <head>
    <script type="text/javascript">
    function test(){
    var map= {'m1': 12,'m2': 13,'m3': 14,'m4': 15}
         alert(map['m3']);
    }
    </script>
    </head>
    <body>
    <input type="button" value="click" onclick="test()"/>
    </body>
    </html>
    

    【讨论】:

      【解决方案5】:

      虽然普通的旧 JavaScript 对象可以用作映射,但它们通常以保留插入顺序的方式实现以与大多数浏览器兼容(请参阅 Craig Barnes 的回答),因此不是简单的哈希映射。

      ES6 引入了正确的 Maps(参见 MDN JavaScript Map),其中 standard says:

      Map 对象必须使用哈希表或其他机制来实现,平均而言,这些机制提供的访问时间与集合中的元素数量呈次线性关系。

      【讨论】:

        【解决方案6】:

        你要不要试试这门课Map:

        var myMap = new Map();
        
        // setting the values
        myMap.set("1", 'value1');
        myMap.set("2", 'value2');
        myMap.set("3", 'value3');
        
        console.log(`Map size: ${myMap.size}`); // 3
        
        // getting the values
        console.log(`Key: "1", Value: ${myMap.get("1")}`);    // "value associated with "value1"
        console.log(`Key: "2", Value: ${myMap.get("2")}`);    // "value associated with "value2"
        console.log(`Key: "3", Value: ${myMap.get("3")}`);    // "value associated with "value3"

        注意:keyvalue 可以是任何类型。

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

        【讨论】:

          【解决方案7】:

          我遇到了带有一些通用键的 json 的问题。我想将所有具有相同键的值分组。经过一番冲浪,我找到了hashmap package。这真的很有帮助。

          为了对具有相同键的元素进行分组,我使用了multi(key:*, value:*, key2:*, value2:*, ...)

          这个包有点类似于 Java Hashmap 集合,但没有 Java Hashmap 强大。

          【讨论】:

            猜你喜欢
            • 2020-08-31
            • 1970-01-01
            • 2021-07-22
            • 1970-01-01
            • 2023-01-18
            • 2016-08-04
            • 1970-01-01
            • 2016-01-25
            • 2019-05-08
            相关资源
            最近更新 更多