Lo más similar a un arreglo asociativo de php en JS es un mapa. Si quieres imitar el comportamiento de inicialización de PHP lo podrías hacer con una función.
let patm = arr => new Map(arr.map((el, i) => Array.isArray(el) ? el : [i, el]));
let m = patm([
'lorem',
'ipsum',
['text', 7]
]);
Para iterar:
m.forEach((el, k) => console.log(el, k));
// 0 'lorem', 1 'ipsum', 'text' 7
También conservas las propiedades que menciona #!drvy
console.log(m.size) //3
console.log([...m.values()]) // ['lorem', 'ipsum', 7]
Lo que no vas a poder hacer es acceder a las propiedades ni siquiera con notación de corchetes.
m[0] = 'test'; //escribe 'test' en la propiedad 0 del objeto del mapa, pero los elementos
//del objeto no son parte del objeto del mapa.
m[1]; //La propiedad 1 del objeto del mapa no es el elemento del mapa al que corresponde la llave 1
m['text']; //Lo mismo de arriba.
Si quieres cambiar esos elementos tienes que usar
Map.prototype.get y
Map.prototype.set:
m.set(0, 'nuevo valor');
console.log(m.get(0)); //'nuevo valor'
Podrías emular ese comportamiento con un Proxy, pero yo no lo haría. Perderías la posibilidad de tener llaves como
forEach,
size,
values,
entries, etc. Sin mencionar que los Proxies son mucho más lentos.
Por otro lado, puedes optar simplemente por un objeto normal:
let obj = {
0 : 'lorem',
1 : 'ipsum',
'text' : 7
};
Y también puedes iterar esas propiedades con
Object.values,
Object.entries y
Object.keys. Pero ojo, a diferencia de PHP y los mapas el orden no está exactamente "garantizado" y no es por orden de inserción. Hasta donde tengo entendido, la especificación no había aclarado un orden al cual todas las implementaciones pudieran llegar de una manera determinista hasta hace poco. Generalmente, las implementaciones se comportan de manera muy similar (al menos en sus últimas versiones).
También puede ser un arreglo:
let a = ['lorem', 'ipsum'];
a['text'] = 7;
console.log(Object.values(a));
Pero ya esto a mi me sabe muy mal.
En mi opinión me quedaba con los mapas de javascript.