如何使用JavaScript/JQuery创建简单地图

200
你如何创建JavaScript/JQuery等效于这个Java代码的版本:
Map map = new HashMap(); //Doesn't not have to be a hash map, any key/value map is fine
map.put(myKey1, myObj1);
map.put(myKey2, myObj2); //Repeat n times

function Object get(k) {
    return map.get(k);
}
6个回答

304

12
我更新了我的答案,使用new Object()代替new Array()。请参考这篇文章 - Simen Echholt
我们如何在这里提供一个根节点? - RK-
1
我们如何从地图中删除一个键值对? - Shikha Dhawan
@Shikha 最有效的方法是简单地放置 (key, null),然后检查您的值是否为 null。否则,请检查如何删除数组中的项目(使用 JavaScript 函数 splice)。 - Adrien Gorrell
4
这个回答已经过时了,因为现在Map已经存在了(耶!),请阅读以下内容:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map - basickarl
显示剩余2条评论

80

只需使用普通对象:

var map = { key1: "value1", key2: "value2" }
function get(k){
  return map[k];
}

键不应该被指定为字符串,即不带引号。 - lilalinux

25
function Map() {
    this.keys = new Array();
    this.data = new Object();

    this.put = function (key, value) {
        if (this.data[key] == null) {
            this.keys.push(key);
        }
        this.data[key] = value;
    };

    this.get = function (key) {
        return this.data[key];
    };

    this.remove = function (key) {
        this.keys.remove(key);
        this.data[key] = null;
    };

    this.each = function (fn) {
        if (typeof fn != 'function') {
            return;
        }
        var len = this.keys.length;
        for (var i = 0; i < len; i++) {
            var k = this.keys[i];
            fn(k, this.data[k], i);
        }
    };

    this.entrys = function () {
        var len = this.keys.length;
        var entrys = new Array(len);
        for (var i = 0; i < len; i++) {
            entrys[i] = {
                key: this.keys[i],
                value: this.data[i]
            };
        }
        return entrys;
    };

    this.isEmpty = function () {
        return this.keys.length == 0;
    };

    this.size = function () {
        return this.keys.length;
    };
}

4
至少将这些方法放在原型上。 - Bergi
4
JavaScript 中使用原型(prototype)与 this 关键字的区别是什么? - Bergi
4
this.data[key] = null 不会删除属性,它只是将属性值设置为 null。你应该使用 delete this.data[key] 来删除属性。 - Michael Scheper
在入口函数中,您应该进行如下更改: entrys[i] = { key: this.keys[i], value: this.data[i] }; -> entrys[i] = { key: this.keys[i], value: this.data[this.keys[i]] }; - Kyung Hwan Min
1
@YoYoYonnY:我不知道柯里化与此有何关系,但原型方法既不会泄漏变量,也不会具有可变作用域。它们确实具有后期绑定的“this”上下文,但这是一种特性而非问题。 - Bergi
显示剩余5条评论

23

虽然这是一个旧问题,但由于现有答案可能非常危险,我想为将来可能会在此处迷失的人留下这个答案...

基于使用对象作为 HashMap 的答案是错误的,如果您使用除字符串以外的任何东西作为键,则可能导致极其恶劣的后果。问题在于对象属性是使用 .toString 方法强制转换为字符串的。这可能会导致以下不良后果:

function MyObject(name) {
  this.name = name;
};
var key1 = new MyObject("one");
var key2 = new MyObject("two");

var map = {};
map[key1] = 1;
map[key2] = 2;

如果您期望Object在此处的行为方式与Java Map相同,那么当您发现map只包含一个String键为[object Object]的条目时,您会感到非常恼火:

> JSON.stringify(map);
{"[object Object]": 2}

很明显,这不是 Java 中 HashMap 的替代品。然而 Javascript 年龄如此之长,却目前没有通用的 map 对象。尽管有希望: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map,但在那里查看浏览器兼容性表格会发现它还没准备好在通用 web 应用程序中使用。

与此同时,你可以做的最好的事情是:

  • 有意识地将字符串作为键。即,使用显式字符串作为键,而不是依赖于所使用的键的 .toString() 隐式转换。
  • 确保你所使用的对象作为键具有定义明确的 .toString() 方法,以适合你对这些对象唯一性的理解。
  • 如果不能或者不想更改键对象的 .toString(),在存储和检索条目时,请将对象转换为表示其唯一性的字符串。例如:map[toUniqueString(key1)] = 1

然而,有时候这是不可能的。如果您想基于 File 对象进行映射,例如,在 JS 中无法可靠地做到这一点,因为 File 对象公开的属性不足以确保其唯一性(您可能有两个代表磁盘上不同文件的 File 对象,但在浏览器中无法区分它们)。在这些情况下,不幸的是,你所能做的就是重构你的代码以消除对存储在 map 中的对象的需求;也许,可以使用数组并仅通过索引引用它们来代替。


18
var map = {'myKey1':myObj1, 'mykey2':myObj2};
// You don't need any get function, just use
map['mykey1']

出于任何原因,我们也可以这样做:var myKey = "myKey1",然后 var map = { [myKey] : myObj1} - Aliton Oliveira

6

如果不限制使用 JQuery,你可以使用 prototype.js 框架。它有一个叫做 Hash 的类:你甚至可以同时使用 JQuery 和 prototype.js。只需输入 jQuery.noConflict();

var h = new Hash();
h.set("key", "value");
h.get("key");
h.keys(); // returns an array of keys
h.values(); // returns an array of values

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接