может ли массив в JS быть ассоциативным и индексированным? Я хотел бы иметь возможность искать элемент в массиве по его позиции или значению ключа. возможно?
Javascript массив ассоциативный И проиндексирован?
Ответ 1
В 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
}
Тем не менее, нет строгого правила о порядке итерации свойств - две итерации вашего литерала объекта могут возвращать свойства в разных порядках.
Ответ 2
После прочтения определения ассоциативного массива Википедии я собираюсь сломать традиционные знания JavaScript и сказать: "Да, у JavaScript есть ассоциативные массивы". С помощью массивов JavaScript вы можете добавлять, переназначать, удалять и искать значения по своим ключам (и ключи могут быть кавычками), что Википедия говорит, что ассоциативные массивы должны быть в состоянии сделать.
Однако вы, кажется, задаете что-то другое - можете ли вы найти то же значение по индексу или ключу. Это не требование ассоциативных массивов (см. Статью в Википедии). Ассоциативные массивы не должны давать вам возможность получать значение по индексу.
Матрицы JavaScript очень близки к объектам JavaScript.
arr=[];
arr[0]="zero";
arr[1]="one";
arr[2]="two";
arr["fancy"]="what?";
Да, это массив, и да, вы можете уйти с нечисловыми индексами. (Если вам интересно, после всего этого, arr.length равно 3.)
В большинстве случаев, я думаю, вы должны придерживаться числовых индексов при использовании массивов. Я думаю, что большинство программистов ожидают.
Ссылка на мое сообщение в блоге о теме.
Ответ 3
Собственные объекты JS принимают только строки как имена свойств, которые являются истинными даже для числовых индексов массива; массивы отличаются от ванильных объектов только в том случае, если большинство реализаций JS будут хранить числовые индексированные свойства по-разному (т.е. в фактическом массиве до тех пор, пока они плотны), и их установка приведет к дополнительным операциям (например, настройке свойства length
).
Если вы ищете карту, которая принимает произвольные ключи, вам придется использовать неродную реализацию. script предназначен для быстрой итерации, а не для произвольного доступа по числовым индексам, поэтому он может и не быть тем, что вы ищете.
Реализация карты, которая будет делать то, что вы просите, будет иметь вид:
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;
};
Аргумент index
put()
не является обязательным.
Вы можете получить доступ к значениям на карте map
либо по клавише, либо по индексу с помощью
map.get('key').value
map[2].value
Ответ 4
Порядок, в котором объекты отображаются в ассоциативном массиве 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];
}
}
Ответ 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"
Ответ 6
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"
Ответ 7
Хотя я согласен с полученными ответами, вы действительно можете выполнить то, что вы говорите, с помощью геттеров и сеттеров. Например:
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
Это то, что вы ищете? я думаю, что это другой более современный способ делать геттеры и сеттеры, но не помню.
Ответ 8
Я пришел сюда, чтобы узнать, плохо ли это или нет, и вместо этого обнаружил, что многие люди не понимают вопроса.
Я хотел иметь структуру данных, которая была заказана, но может быть проиндексирована ключом, так что для каждого поиска не потребуется итерация.
В практические времена это довольно просто, но я до сих пор ничего не читал о том, ужасная практика или нет.
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);
Важно, чтобы никогда не изменять значение массива [index] или array [key] непосредственно после того, как объект настроен, или значения больше не будут соответствовать. Если массив содержит объекты, вы можете изменить свойства этих объектов, и вы сможете получить доступ к измененным свойствам любым способом.
Ответ 9
Прилив изменился на этом. Теперь вы можете сделать это... и БОЛЬШЕ! Используя Harmony Proxies, вы могли бы решить эту проблему во многих отношениях.
Вам нужно будет убедиться, что ваши целевые среды поддерживают это, возможно, небольшую помощь из harmony-reflect shim.
Там действительно хороший пример в Mozilla Developer Network по использованию прокси-сервера для найти объект элемента массива по своему свойству, который в значительной степени его суммирует вверх.
Здесь моя версия:
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 }
Ответ 10
Да.
test = new Array();
test[0] = 'yellow';
test['banana'] = 0;
alert(test[test['banana']]);