2010-03-24 16 views
65

ho un array creato con questo codice:Come ottenere le chiavi dell'array in Javascript?

var widthRange = new Array(); 
widthRange[46] = { min:0, max:52 }; 
widthRange[66] = { min:52, max:70 }; 
widthRange[90] = { min:70, max:94 }; 

voglio ottenere ciascuno dei valori 46, 66, 90 in un ciclo. Ho provato for (var key in widthRange) ma questo mi dà un sacco di proprietà extra (presumo che siano funzioni sull'oggetto). Non riesco a utilizzare un ciclo for regolare poiché i valori non sono sequenziali.

+8

Sembra che tu abbia dati che, mentre capita di avere tasti numerici, non sono in realtà dati di array. Guarderei usando un oggetto normale qui. Gli array – Quentin

risposta

87

, è necessario chiamare la funzione hasOwnProperty a controlla se la proprietà è effettivamente definita sull'oggetto stesso (al contrario del suo prototipo), come questo:

for (var key in widthRange) { 
    if (key === 'length' || !widthRange.hasOwnProperty(key)) continue; 
    var value = widthRange[key]; 
} 

Nota che è necessario un controllo separato per length.
Tuttavia, non dovresti utilizzare un array qui; dovresti usare un oggetto regolare. Tutti gli oggetti Javascript funzionano come array associativi.

Ad esempio:

var widthRange = { }; //Or new Object() 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 
+2

Davvero? Wow imparo qualcosa ogni giorno qui, e così spesso è da te SLaks :-) Sono sorpreso che Array tenga traccia dei suoi indici esplicitamente impostati in questo modo. Forse non dovrei esserlo. – Pointy

+0

@SLaks: Grazie, cambiarlo in un oggetto sembra la soluzione migliore. Un'altra domanda: c'è un modo per scorrere in ordine inverso? – DisgruntledGoat

+0

No; dovrai farlo da solo – SLaks

3
for (var i = 0; i < widthRange.length; ++i) { 
    if (widthRange[i] != null) { 
    // do something 
    } 
} 

Non si può davvero ottenere solo le chiavi che hai impostato, perché non è così che funziona un array. Una volta che hai impostato l'elemento 46, hai anche impostato da 0 a 45 (anche se sono nulli).

Si può sempre avere due array:

var widthRange = [], widths = [], newVal = function(n) { 
    widths.push(n); 
    return n; 
}; 
widthRange[newVal(26)] = { whatever: "hello there" }; 

for (var i = 0; i < widths.length; ++i) { 
    doSomething(widthRange[widths[i]]); 
} 

modifica bene può essere che io sono tutto bagnato qui ...

+0

tengono traccia della lunghezza, non passano e creano comunque molti oggetti. Fondamentalmente, quando viene trovato un nuovo indice, controlla se quel nuovo indice è maggiore della lunghezza ... se è che il nuovo indice diventa la nuova lunghezza. A causa di ciò, è possibile ottenere solo gli indici definite con un ciclo for-in – Bob

1

tuo esempio originale funziona bene per me:

<html> 
<head> 
</head> 
<body> 
<script> 
var widthRange = new Array(); 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 

var i = 1; 
for (var key in widthRange) 
{ 
    document.write("Key #" + i + " = " + key + "; &nbsp;&nbsp;&nbsp; min/max = " + widthRange[key].min + "/" + widthRange[key].max + "<br />"); 
    i++; 
} 
</script> 
</html> 

risultati nel browser (Firefox 3.6.2 su Windows XP):

Key #1 = 46;  min/max = 0/52 
Key #2 = 66;  min/max = 52/70 
Key #3 = 90;  min/max = 70/94 
+2

Scommetto che sta importando il prototipo o qualcosa del genere. In generale, questi loop "in" sono rischiosi. – Pointy

+0

Bene, sto usando jQuery ma anche Joomla che usa mootools, qualcosa sta aggiungendo queste proprietà. – DisgruntledGoat

0

Sembra funzionare.

var widthRange = new Array(); 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 

for (var key in widthRange) 
{ 
    document.write(widthRange[key].sel + "<br />"); 
    document.write(widthRange[key].min + "<br />"); 
    document.write(widthRange[key].max + "<br />"); 
} 
1

Penso che si dovrebbe utilizzare un oggetto ({}) e non un array ([]) per questo.

Un insieme di dati è associato a ciascun tasto. Urla per l'utilizzo di un oggetto. Non:

var obj = {}; 
obj[46] = { sel:46, min:0, max:52 }; 
obj[666] = { whatever:true }; 

// This is what for..in is for 
for (var prop in obj) { 
    console.log(obj[prop]); 
} 

Forse alcune cose programma di utilità come questo può aiutare:

window.WidthRange = (function() { 
    var obj = {}; 
    return { 
    getObj: function() {return obj;} 
    , add: function (key, data) { 
     obj[key] = data; 
     return this; // enabling chaining 
     } 
    } 
})(); 

// Usage (using chaining calls): 
WidthRange.add(66, {foo: true}) 
.add(67, {bar: false}) 
.add(69, {baz: 'maybe', bork:'absolutely'}); 

var obj = WidthRange.getObj(); 
for (var prop in obj) { 
    console.log(obj[prop]); 
} 
18

Se stai facendo qualsiasi tipo di array di manipolazione/raccolta o l'ispezione Consiglio vivamente l'utilizzo Underscore.js. È piccolo, ben testato e ti farà risparmiare giorni/settimane/anni di mal di testa javascript. Qui è la sua funzione tasti:

Keys

recuperare tutti i nomi delle proprietà dell'oggetto.

_.keys({one : 1, two : 2, three : 3}); 
=> ["one", "two", "three"] 
0

ho scritto una funzione di ciò che funziona bene con ogni istanza di oggetti (array sono quelli).

Object.prototype.toArray = function() 
{ 
    if(!this) 
    { 
     return null; 
    } 

    var c = []; 

    for (var key in this) 
    { 
     if ((this instanceof Array && this.constructor === Array && key === 'length') || !this.hasOwnProperty(key)) 
     { 
      continue; 
     } 

     c.push(this[key]); 
    } 

    return c; 
}; 

Usage:

var a = [ 1, 2, 3 ]; 
a[11] = 4; 
a["js"] = 5; 

console.log(a.toArray()); 

var b = { one: 1, two: 2, three: 3, f: function() { return 4; }, five: 5 }; 
b[7] = 7; 

console.log(b.toArray()); 

uscita:

> [ 1, 2, 3, 4, 5 ] 
> [ 7, 1, 2, 3, function() { return 4; }, 5 ] 

Può essere utile per chiunque.

+2

Estensione di un prototipo che non è stato creato è una pessima idea, non importa quanto sia conveniente si pensa che è. – doug65536

54

Le chiavi stringata possono essere interrogati con Object.keys(array).

+2

grazie, proprio quello di cui avevo bisogno. – spazm

+0

Questo restituisce le chiavi come stringhe, non numeri, solo così tutti sono a conoscenza. –

0

... ????

In alternativa, se si dispone di un elenco di elementi che si desidera utilizzare ...

var range = [46, 66, 90] 
    , widthRange=[] 
    , write=[]; 

    widthRange[46] = { min:0, max:52 }; 
    widthRange[66] = { min:52, max:70 }; 
    widthRange[90] = { min:70, max:94 }; 

for(var x=0; x<range.length; x++){var key, wr; 

    key = range[x]; 

    wr = widthRange[key] || false; 

    if(wr===false){continue;} 

    write.push(['key: #',key, ', min: ', wr.min, 'max:', wr.max].join('')); 

    } 
2

Di 'la matrice sembrava arr = [ { a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }, { a: 7, b: 8, c: 9 } ] (o, eventualmente, altri tasti) si potrebbe fare

arr.map((o) => { 
    return Object.keys(o) 
}).reduce((prev, curr) => { 
    return prev.concat(curr) 
}).filter((col, i, array) => { 
    return array.indexOf(col) === i 
}); 

["a", "b", "c"]

2
widthRange.map(function(_, i) { return i }); 

o

widthRange.map((_, i) => i); 
Problemi correlati