Javascript 数组是关联的还是索引的?

Javascript 数组是关联的还是索引的?,javascript,arrays,indexing,associative,Javascript,Arrays,Indexing,Associative,JavaScript中的数组是否可以关联和索引 我希望能够通过位置或键值查找数组中的项。关联javascript数组中对象的显示顺序没有定义,并且在不同的实现中会有所不同。因此,您不能指望给定的关联键始终位于同一索引 编辑: 正如Perspx指出的,javascript中并没有真正的关联数组。语句foo[“bar”]只是foo.bar 如果您信任浏览器维护对象中元素的顺序,则可以编写函数 function valueForIndex(obj, index) { var i = 0;

JavaScript中的数组是否可以关联和索引


我希望能够通过位置或键值查找数组中的项。

关联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];
    }
}

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

例如,对于此对象:

var params = {
    foo: 1,
    bar: 0,
    other: 2
};
可以从对象访问属性,例如:

params["foo"];
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
您还可以使用
for…in
语句对对象进行迭代:

for(var v in params) {
    //v is equal to the currently iterated property
}
但是,对于属性迭代的顺序没有严格的规定-对象文本的两次迭代可能会以不同的顺序返回属性。

阅读后,我将打破传统的JavaScript知识,说:“是的,JavaScript确实有关联数组。”使用JavaScript数组,您可以添加、重新分配、删除,通过键查找值(键可以是带引号的字符串),这就是维基百科所说的关联数组应该能够做到的

然而,您似乎在问一些不同的问题——是否可以通过索引或键查找相同的值。这不是关联数组的要求(请参阅Wikipedia文章)。关联数组不必提供按索引获取值的功能

是的,这是一个数组,是的,你可以不使用非数字索引。(如果你好奇的话,在所有这些之后,arr.length是3。)

在大多数情况下,我认为在使用数组时应该坚持使用数字索引。我认为这是大多数程序员所期望的


该链接指向我关于该主题的博客文章。

原生JS对象只接受字符串作为属性名,这是正确的;数组与普通对象的不同之处在于,大多数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;
};


虽然我同意你给出的答案,但你可以用能手和二传手完成你所说的。例如:

params["foo"];
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 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 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);
var-roygbiv=[];
var color={key:“red”,hex:#FF0000};
罗伊格比推(彩色);
罗伊格比[color.key]=颜色;
...
原木(“彩虹的六边形颜色顺序:”);
对于(变量i=0;i

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

此方法的潮流已经改变。现在你可以做到了。。。还有更多!使用Harmony代理肯定可以在许多方面解决这个问题

您必须验证您的目标环境是否支持这一点,可能需要来自shim的一点帮助

在Mozilla开发者网络上有一个非常好的例子,就是使用代理,这在很大程度上是对它的总结

以下是我的版本:

  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 }
var players=新代理(
[{
名字:“猴子”,
分数:50
}, {
名称:“长颈鹿”,
分数:100
}, {
名称:“鹈鹕”,
分数:150
}], {
获取:功能(对象、道具){
if(obj中的支柱){
//默认行为
返回对象[prop];
}
if(typeof prop==“string”){
如果(prop=='rank'){
返回对象排序(函数(a,b){
返回a.score>b.score?-1:1;
});
}
如果(prop=='revrank'){
返回对象排序(函数(a,b){
返回a.得分score){
分数=玩家的分数;
赢家=玩家;
}
}
如果(道具=‘获胜者’){
返回赢家;
}
返回;
}
}
});
console.log(玩家[0]);//{名字:'猴子',分数:50}
console.log(玩家['monkey']);//{名字:'猴子',分数:50}
console.log(玩家['zeb
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);
  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 }
let arr=[];
 arr[0]="zero";
 arr[1]="one";
 arr[2]="two";
 arr["fancy"]="what?";

//Arrays cannot use strings as element indexes (as in an associative array) but must use integers. 
//Setting non-integers using bracket notation will not set an element to the Array List itself
//A non-integer will set a variable associated with that ARRAY Object property collection 
let denseKeys = [...arr.keys()];
console.log(denseKeys);//[ 0, 1, 2 ]
console.log("ARRAY Keys:"+denseKeys.length);//3


let sparseKeys = Object.keys(arr);
console.log(sparseKeys);//[ '0', '1', '2', 'fancy' ]
console.log("Object Keys:"+sparseKeys.length);//4

const iterator = arr.keys();
for (const key of iterator) {
  console.log(key);//0,1,2
}