¿Cómo acceder a la primera propiedad de un objeto Javascript?

611

¿Existe una manera elegante de acceder a la primera propiedad de un objeto ...

  1. donde no sabes el nombre de tus propiedades
  2. sin usar un bucle como for .. ino jQuery$.each

Por ejemplo, necesito acceder al foo1objeto sin saber el nombre de foo1:

var example = {
    foo1: { /* stuff1 */},
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};
atogle
fuente
1
probablemente sea mejor transformarlo en una matriz primero
cregox

Respuestas:

1393
var obj = { first: 'someVal' };
obj[Object.keys(obj)[0]]; //returns 'someVal'

Con esto, también puede acceder a otras propiedades por índices. ¡Ten cuidado! Object.keysel pedido de devolución no está garantizado según ECMAScript; sin embargo, de manera extraoficial se encuentra en todas las implementaciones de navegadores principales, lea https://stackoverflow.com/a/23202095 para obtener más información al respecto.

Grzegorz Kaczan
fuente
25
Dices que no es la forma más rápida. ¿De qué manera sería más rápido?
T Nguyen
3
Esto no es muy eficiente, ya que crea una matriz completa de todas las claves del objeto.
Andrew Mao
99
@T Nguyen Lo publicaría si lo supiera :)
Grzegorz Kaczan
55
@DavChana: tenía su punto de referencia configurado incorrectamente. El bloque repetitivo siempre se ejecutará y su bloque 2 estaba vacío, lo que significa que el primer resultado representa la ejecución repetitiva + bloque1 , y el segundo resultado representa solo repetitivo . Aquí está el punto de referencia correcto: http://jsben.ch/#/R9aLQ , que muestra que son prácticamente iguales (ejecute la prueba varias veces).
myfunkyside
99
Desearía first()o algo similar podría manejar esto.
Fr0zenFyr
113

Pruebe el for … inciclo y rompa después de la primera iteración:

for (var prop in object) {
    // object[prop]
    break;
}
Gumbo
fuente
1
Creo que esta es la única opción. Sin embargo, no estoy seguro de que esté garantizado de que las propiedades se iterarán en un orden predecible / útil. Es decir, puede pretender foo1 pero obtener foo3. Si las propiedades están numeradas como en el ejemplo, puede hacer una comparación de cadena para determinar el identificador que termina en '1'. Por otra parte, si la ordinalidad es la principal preocupación de la colección, probablemente debería usar una matriz en lugar de un objeto.
steamer25
2
Si alguien más está preocupado por el pedido, la mayoría de los navegadores se comportan de manera predecible: stackoverflow.com/questions/280713/…
Flash
66
var prop; para (apoyo en objeto) descanso; // object [prop]
netiul
12
Antigua respuesta pero. Es posible que desee verificar si la propiedad pertenece al objeto. como: for (..) {if (! obj.hasOwnProperty (prop)) continue; .... rotura; } en caso de que el objeto esté realmente vacío, no atraviesa el prototipo o algo así.
pgarciacamou
47

Se usa Object.keyspara obtener una matriz de las propiedades de un objeto. Ejemplo:

var example = {
    foo1: { /* stuff1 */},
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};

var keys = Object.keys(example); // => ["foo1", "foo2", "foo3"] (Note: the order here is not reliable)

Documentación y shim entre navegadores provistos aquí . Un ejemplo de su uso se puede encontrar en otra de mis respuestas aquí .

Editar : para mayor claridad, solo quiero hacer eco de lo que se dijo correctamente en otras respuestas: el orden de las claves en los objetos de JavaScript no está definido.

benekastah
fuente
25

Una versión de una regla:

var val = example[function() { for (var k in example) return k }()];
netiul
fuente
2
A veces puede ser arriesgado usarlo for insin verificarlo, hasOwnPropertyya que el objeto contiene otros valores no deseados agregados programáticamente para que pueda obtener un resultado no deseado de este fragmento. El hecho de que sea corto y ordenado no significa que sea óptimo de forma segura.
Javier Cobos
24

No hay una "primera" propiedad. Las claves de objeto no están ordenadas.

Si los repite (var foo in bar), los obtendrá en algún orden, pero puede cambiar en el futuro (especialmente si agrega o elimina otras claves).

Quentin
fuente
Increíble. He estado usando un objeto para implementar un mapa que mantiene el orden de inserción. Eso se rompe una vez que elimino un valor porque la siguiente inserción llena el espacio. :(
David Harkness
2
El orden de clave / valor debe conservarse en las versiones más recientes de JS
Alexander Mills
11

Solución con la biblioteca lodash :

_.find(example) // => {name: "foo1"}

pero no hay garantía del orden de almacenamiento interno de las propiedades del objeto porque depende de la implementación de la máquina virtual javascript.

pocheptsov
fuente
2
Acabo de probar esto, y no funciona. Solo devuelve el valor, no el par clave / valor.
Chris Haines
2
No se menciona en la pregunta que debería devolver el par clave / valor, solo pregunta por el objeto y la respuesta aceptada hace tanto como esta función lodash: devuelve el contenido de la primera propiedad. Puede que no se adapte a sus necesidades específicas, pero esta respuesta es correcta según la pregunta original.
Carrm
Sí, el trabajo es útil cuando sabes que tu objeto tendrá un solo objeto hijovar object = { childIndex: { .. } }; var childObject = _.find(Object);
Raja Khoury
9

No. Un objeto literal, como lo define MDC es:

una lista de cero o más pares de nombres de propiedades y valores asociados de un objeto, encerrados entre llaves ({}).

Por lo tanto, un objeto literal no es una matriz, y solo puede acceder a las propiedades con su nombre explícito o un forbucle con la inpalabra clave.

Alex Rozanski
fuente
25
Para otros que solo ven el tic verde en esta respuesta, hay otra solución más abajo en la página con actualmente 350 votos a favor.
redfox05
7

La respuesta principal podría generar toda la matriz y luego capturarla de la lista. Aquí hay otro atajo efectivo

var obj = { first: 'someVal' };
Object.entries(obj)[0][1] // someVal
kishorekumaru
fuente
3

Esto ha sido cubierto aquí antes.

El concepto de primero no se aplica a las propiedades de los objetos, y el orden de un bucle for ... in no está garantizado por las especificaciones, sin embargo, en la práctica, es confiable FIFO excepto críticamente para Chrome ( informe de error ). Tome sus decisiones en consecuencia.

annakata
fuente
3

No le recomiendo que use Object.keys ya que no es compatible con versiones antiguas de IE. Pero si realmente lo necesita, puede usar el código anterior para garantizar la compatibilidad con la parte posterior:

if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
    hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
    dontEnums = [
      'toString',
      'toLocaleString',
      'valueOf',
      'hasOwnProperty',
      'isPrototypeOf',
      'propertyIsEnumerable',
      'constructor'
    ],
    dontEnumsLength = dontEnums.length;

return function (obj) {
  if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

  var result = [];

  for (var prop in obj) {
    if (hasOwnProperty.call(obj, prop)) result.push(prop);
  }

  if (hasDontEnumBug) {
    for (var i=0; i < dontEnumsLength; i++) {
      if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
    }
  }
  return result;
}})()};

Característica Firefox (Gecko) 4 (2.0) Chrome 5 Internet Explorer 9 Opera 12 Safari 5

Más información: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

Pero si solo necesita el primero, podríamos organizar una solución más corta como:

var data = {"key1":"123","key2":"456"};
var first = {};
for(key in data){
    if(data.hasOwnProperty(key)){
        first.key = key;
        first.content =  data[key];
        break;
    }
}
console.log(first); // {key:"key",content:"123"}
Javier Cobos
fuente
2

Para obtener el primer nombre clave en el objeto, puede usar:

var obj = { first: 'someVal' };
Object.keys(obj)[0]; //returns 'first'

Devuelve una cadena, por lo que no puede acceder a objetos anidados si hubiera, como:

var obj = { first: { someVal : { id : 1} }; Aquí con esa solución no puede acceder a la identificación.

La mejor solución si desea obtener el objeto real es usar lodash como:

obj[_.first(_.keys(obj))].id

Para devolver el valor de la primera clave (si no sabe exactamente el nombre de la primera clave):

var obj = { first: 'someVal' };
obj[Object.keys(obj)[0]]; //returns 'someVal'

si conoce el nombre de la clave, simplemente use:

obj.first

o

obj['first']
Diego Unanue
fuente
0

Si necesita acceder a "la primera propiedad de un objeto", puede significar que hay algo mal con su lógica. El orden de las propiedades de un objeto no debería importar.

Flavius ​​Stef
fuente
Tienes razón. No necesito el primero, per se, pero solo una de las propiedades foo para poder trabajar con él. Sólo tengo uno y no estaba segura de si había una manera sólo para agarrar el "primero" uno sin el uso de for ... in.
atogle
0

Use una matriz en lugar de un objeto (corchetes).

var example = [ {/* stuff1 */}, { /* stuff2 */}, { /* stuff3 */}];
var fist = example[0];

Tenga en cuenta que pierde los identificadores 'foo'. Pero podría agregar una propiedad de nombre a los objetos contenidos:

var example = [ 
  {name: 'foo1', /* stuff1 */},
  {name: 'foo2', /* stuff2 */},
  {name: 'foo3', /* stuff3 */}
];
var whatWasFirst = example[0].name;
vapor25
fuente
Hay situaciones en las que no podemos. Asumimos que no podemos cambiar el hecho de que no están en una matriz
1mike12
1
Creo que es útil retrasar un poco el diseño para los lectores que pueden controlar su esquema JSON. Esencialmente, estoy extendiendo la respuesta de Flavius ​​Stef con algunos ejemplos.
steamer25
0

¿Alguna razón para no hacer esto?

> example.map(x => x.name);

(3) ["foo1", "foo2", "foo3"]
jtr13
fuente
8
Porque .map()solo existe para iterables
integrados
0

Puede usar Object.prototype.keyscual devuelve todas las claves de un objeto en el mismo orden. Entonces, si desea el primer objeto, simplemente obtenga esa matriz y use el primer elemento como clave deseada.

const o = { "key1": "value1", "key2": "value2"};
const idx = 0; // add the index for which you want value
var key = Object.keys(o)[idx];
value = o[key]
console.log(key,value); // key2 value2
akash kumar
fuente
1
Al responder una pregunta anterior, su respuesta sería mucho más útil para otros usuarios de StackOverflow si incluyera algún contexto para explicar cómo ayuda su respuesta, particularmente para una pregunta que ya tiene una respuesta aceptada. Ver: ¿Cómo escribo una buena respuesta ?
David Buck
0

También podemos hacer con este enfoque.

var example = {
  foo1: { /* stuff1 */},
  foo2: { /* stuff2 */},
  foo3: { /* stuff3 */}
}; 
Object.entries(example)[0][1];
Salil Sharma
fuente
0

Aquí hay una forma más limpia de obtener la primera clave:

var example = {
    foo1: { /* stuff1 */},
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};

var object2 = {
    needThis: 'This is a value of the property',
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};

let [first] = Object.keys(example)
let [firstProp] = Object.keys(object2)

console.log(first)
//Prop : needThis, Value: This is a value of the property
console.log(`Prop : ${firstProp}, Value: ${object2[firstProp]}`)

Ntiyiso Rikhotso
fuente
Pero por qué la matriz alrededor [first]. El usuario no solicitó una matriz como respuesta. ¿Por qué hacer esto sobre lo first = Object.keys(example)[0]que hará lo mismo sin necesidad de ajustar la respuesta en una matriz? ¿Por qué el tuyo es más limpio, por favor?
Michael Durrant
Esa es una tarea de desestructuración developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ntiyiso Rikhotso