JavaScript数组关联和索引?

JS中的数组可以联合和索引? 我希望能够通过它的位置或一个键值来查找数组中的项目。可能吗?

Javascript中没有像关联数组这样的事情。 您可以使用对象字面值,它看起来像关联数组,但它们具有无序的属性。 常规的Javascript数组基于整数索引,不能关联。

例如,用这个对象:

var params = { foo: 1, bar: 0, other: 2 }; 

您可以从对象访问属性,例如:

 params["foo"]; 

你也可以使用for...in语句迭代对象:

 for(var v in params) { //v is equal to the currently iterated property } 

但是,对于属性迭代的顺序没有严格的规则 – 对象文本的两次迭代可能会以不同的顺序返回属性。

在阅读关联数组的维基百科定义之后,我将打破传统的JavaScript知识并说:“是的,JavaScript确实有关联数组”。 使用JavaScript数组,您可以按键添加,重新分配,删除和查找值(而且键可以是带引号的string),这就是维基百科所说的关联数组应该能够做到的。

然而,你似乎在问不同的东西 – 你是否可以通过索引或键来查找相同的值。 这不是关联数组的要求(请参阅维基百科文章)。关联数组不必让您通过索引获取值。

JavaScript数组非常类似于JavaScript对象。

  arr=[]; arr[0]="zero"; arr[1]="one"; arr[2]="two"; arr["fancy"]="what?"; 

是的,这是一个数组,是的,你可以逃脱非数字指数。 (如果你好奇,毕竟这个是arr.length是3.)

在大多数情况下,我认为你应该坚持使用数组的数字指标。 这是大多数程序员期望的,我想。

链接是关于这个主题的博客文章。

原生JS对象只接受string作为属性名称, 即使对于数字数组索引也是如此; 只有在大多数JS实现以不同的方式存储数字索引属性的情况下(即在实际数组中,只要它们是密集的),并且设置它们将触发额外的操作(例如调整length属性),数组就不同于香草对象。

如果您正在查找接受任意键的映射,则必须使用非本机实现 。 该脚本的目的是快速迭代,而不是随机访问的数字指数,所以它可能也不是你在找什么。

一个可以做你想要的地图的准系统实现可能看起来像这样:

 function Map() { this.length = 0; this.store = {}; } Map.prototype.get = function(key) { return this.store.hasOwnProperty(key) ? this.store[key] : undefined; }; Map.prototype.put = function(key, value, index) { if(arguments.length < 3) { if(this.store.hasOwnProperty(key)) { this.store[key].value = value; return this; } index = this.length; } else if(index >>> 0 !== index || index >= 0xffffffff) throw new Error('illegal index argument'); if(index >= this.length) this.length = index + 1; this[index] = this.store[key] = { index : index, key : key, value : value }; return this; }; 

put()index参数是可选的。

您可以通过键或索引通过访问地图map的值

 map.get('key').value map[2].value 

对象出现在关联JavaScript数组中的顺序没有定义,并且在不同的实现中会有所不同。 出于这个原因,你不能真正指望一个给定的联想键总是在同一个索引。

编辑:

正如Perspx指出的那样,在javascript中并没有真正的关联数组。 语句foo["bar"]只是foo.bar语法糖

如果您信任浏览器以维护对象中元素的顺序,则可以编写一个函数

 function valueForIndex(obj, index) { var i = 0; for (var key in obj) { if (i++ == index) return obj[key]; } } 
 var myArray = Array(); myArray["first"] = "Object1"; myArray["second"] = "Object2"; myArray["third"] = "Object3"; Object.keys(myArray); // returns ["first", "second", "third"] Object.keys(myArray).length; // returns 3 

如果你想要第一个元素,那么你可以像这样使用它:

 myArray[Object.keys(myArray)[0]]; // returns "Object1" 
 var stuff = []; stuff[0] = "foo"; stuff.bar = stuff[0]; // stuff.bar can be stuff["bar"] if you prefer var key = "bar"; alert(stuff[0] + ", " + stuff[key]); // shows "foo, foo" 

虽然我同意给出的答案,你可以实际完成你正在说的与getter和setter。 例如:

 var a = [1]; //This makes a["blah"] refer to a[0] a.__defineGetter__("blah", function(){return this[0]}); //This makes a["blah"] = 5 actually store 5 into a[0] a.__defineSetter__("blah", function(val){ this[0] = val}); alert(a["blah"]); // emits 1 a["blah"] = 5; alert(a[0]); // emits 5 

这是你想要的? 我觉得这是一个不同的更现代的方式来做吸气剂和二手烟,但不记得。

我来这里是想知道这是不是好的做法,而是发现很多人似乎不明白这个问题。

我想要一个有序的数据结构,但可以通过键索引,这样就不需要每次查找都要迭代。

我这个实际的时代很简单,但是我还没有看过是否是一个可怕的做法。

 var roygbiv = []; var colour = { key : "red", hex : "#FF0000" }; roygbiv.push(colour); roygbiv[colour.key] = colour; ... console.log("Hex colours of the rainbow in order:"); for (var i = 0; i < roygbiv.length; i++) { console.log(roygbiv[i].key + " is " + roygbiv[i].hex); } // input = "red"; console.log("Hex code of input colour:"); console.log(roygbiv[input].hex); 

重要的是,一旦对象被设置或值不再匹配,就不要直接改变array [index]或array [key]的值。 如果数组包含对象,则可以更改这些对象的属性,并且可以通过任一方法访问已更改的属性。

这个潮stream已经改变了。 现在你可以做到这一点…和更多! 使用Harmony Proxies,你可以在很多方面解决这个问题。

你必须validation你的目标环境是否可以从和谐reflection垫片中得到一些帮助。

在Mozilla开发者networking上有一个非常好的例子,它使用代理通过它的属性查找数组项目对象,这几乎可以总结出来。

这是我的版本:

  var players = new Proxy( [{ name: 'monkey', score: 50 }, { name: 'giraffe', score: 100 }, { name: 'pelican', score: 150 }], { get: function(obj, prop) { if (prop in obj) { // default behavior return obj[prop]; } if (typeof prop == 'string') { if (prop == 'rank') { return obj.sort(function(a, b) { return a.score > b.score ? -1 : 1; }); } if (prop == 'revrank') { return obj.sort(function(a, b) { return a.score < b.score ? -1 : 1; }); } var winner; var score = 0; for (var i = 0; i < obj.length; i++) { var player = obj[i]; if (player.name == prop) { return player; } else if (player.score > score) { score = player.score; winner = player; } } if (prop == 'winner') { return winner; } return; } } }); console.log(players[0]); // { name: 'monkey', score: 50 } console.log(players['monkey']); // { name: 'monkey', score: 50 } console.log(players['zebra']); // undefined console.log(players.rank); // [ { name: 'pelican', score: 150 },{ name: 'giraffe', score: 100 }, { name: 'monkey', score: 50 } ] console.log(players.revrank); // [ { name: 'monkey', score: 50 },{ name: 'giraffe', score: 100 },{ name: 'pelican', score: 150 } ] console.log(players.winner); // { name: 'pelican', score: 150 } 

是。

 test = new Array(); test[0] = 'yellow'; test['banana'] = 0; alert(test[test['banana']]);