Jak uzyskać dostęp do pierwszej właściwości obiektu JavaScript?

611

Czy istnieje elegancki sposób na uzyskanie dostępu do pierwszej właściwości obiektu ...

  1. gdzie nie znasz nazwy swoich nieruchomości
  2. bez użycia pętli jak for .. inlub jQuery$.each

Na przykład muszę uzyskać dostęp do foo1obiektu bez znajomości nazwy foo1:

var example = {
    foo1: { /* stuff1 */},
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};
atogle
źródło
1
prawdopodobnie lepiej najpierw przekształcić go w macierz
cregox

Odpowiedzi:

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

Za pomocą tego można uzyskać dostęp do innych właściwości według indeksów. Bądź tego świadomy! Object.keyszamówienie zwrotu nie jest gwarantowane zgodnie z ECMAScript, jednak nieoficjalnie dzieje się tak we wszystkich głównych implementacjach przeglądarek. Szczegółowe informacje na ten temat można znaleźć na stronie https://stackoverflow.com/a/23202095 .

Grzegorz Kaczan
źródło
25
Mówisz, że to nie jest najszybszy sposób. Który sposób byłby szybszy?
T Nguyen,
3
Nie jest to bardzo wydajne, ponieważ tworzy całą tablicę wszystkich kluczy obiektu.
Andrew Mao
9
@T Nguyen Zamieszczę go, gdybym wiedział :)
Grzegorz Kaczan
5
@DavChana - Źle skonfigurowano test porównawczy. Blok boilerplate zawsze będą realizowane i twój blok 2 była pusta, co oznacza, że pierwszy wynik reprezentuje wykonanie boilerplate + blok1 , a drugi wynik reprezentuje tylko szablonowe . Oto poprawny test porównawczy: http://jsben.ch/#/R9aLQ , pokazujący, że są one prawie równe (uruchom test wiele razy).
myfunkyside
9
Chciałbym first()lub coś podobnego mogłoby to poradzić.
Fr0zenFyr,
113

Wypróbuj for … inpętlę i przerwij po pierwszej iteracji:

for (var prop in object) {
    // object[prop]
    break;
}
Gumbo
źródło
1
Myślę, że jest to jedyna opcja. Nie jestem jednak pewien, że masz gwarancję, że właściwości będą iterowane w przewidywalnej / użytecznej kolejności. To znaczy, możesz chcieć foo1, ale dostaniesz foo3. Jeśli właściwości są ponumerowane jak w przykładzie, można wykonać ciąg znaków w celu porównania identyfikatora kończącego się na „1”. Z drugiej strony, jeśli porządek jest głównym przedmiotem kolekcji, prawdopodobnie powinieneś użyć tablicy zamiast obiektu.
parowiec25
2
Jeśli ktokolwiek jest zaniepokojony zamówieniem, większość przeglądarek zachowuje się przewidywalnie: stackoverflow.com/questions/280713/…
Flash
6
var prop; do przerwania (prop w obiekcie); // object [prop]
netto
12
Stara odpowiedź, ale. Możesz sprawdzić, czy właściwość należy do obiektu. jak: for (..) {if (! obj.hasOwnProperty (prop)) kontynuuj; .... przerwa; } na wypadek, gdyby obiekt był faktycznie pusty, nie przechodzi on przez prototyp ani coś takiego.
pgarciacamou
46

Użyj, Object.keysaby uzyskać tablicę właściwości obiektu. Przykład:

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

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

Dokumentacja i podkładka między przeglądarkami tutaj . Przykład jego użycia można znaleźć w innej z moich odpowiedzi tutaj .

Edycja : dla jasności chcę tylko powtórzyć to, co zostało poprawnie stwierdzone w innych odpowiedziach: kolejność klawiszy w obiektach javascript jest niezdefiniowana.

benekastah
źródło
25

Wersja z jedną zasadą:

var val = example[function() { for (var k in example) return k }()];
netiul
źródło
2
Czasami korzystanie z niego for inbez sprawdzania może być ryzykowne, hasOwnPropertyponieważ obiekt zawiera inne niechciane wartości dołączane do niego programowo, dzięki czemu można uzyskać niechciany wynik z tego fragmentu kodu. Tylko dlatego, że jest krótki i schludny, nie oznacza, że ​​jest bezpieczny.
Javier Cobos,
24

Nie ma „pierwszej” właściwości. Klucze obiektowe są nieuporządkowane.

Jeśli je (var foo in bar)zapętlisz, dostaniesz je w określonej kolejności, ale może się to zmienić w przyszłości (zwłaszcza jeśli dodasz lub usuniesz inne klucze).

Quentin
źródło
Niesamowite. Używam obiektu do implementacji mapy, która zachowuje porządek wstawiania. To się psuje, gdy usunę wartość, ponieważ następne wstawienie wypełnia lukę. :(
David Harkness
2
kolejność kluczy / wartości powinna być zachowana w nowszych wersjach JS
Alexander Mills,
11

Rozwiązanie z biblioteką lodash :

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

ale nie ma gwarancji kolejności obiektów w pamięci wewnętrznej, ponieważ zależy to od implementacji maszyny Wirtualnej javascript.

pocheptsov
źródło
2
Właśnie to przetestowałem i to nie działa. Zwraca tylko wartość, a nie parę klucz / wartość.
Chris Haines,
2
W pytaniu nie ma wzmianki, że powinna zwrócić parę klucz / wartość, on po prostu prosi o obiekt, a zaakceptowana odpowiedź robi tyle samo, co funkcja lodash: zwraca zawartość pierwszej właściwości. Może nie pasować do twoich konkretnych potrzeb, ale ta odpowiedź JEST poprawna na podstawie pierwotnego pytania.
Carrm
Tak, spełnia swoje zadanie, przydatne, gdy wiesz, że Twój obiekt będzie miał tylko jeden obiekt podrzędnyvar object = { childIndex: { .. } }; var childObject = _.find(Object);
Raja Khoury
9

Nie. Literał obiektowy, zgodnie z definicją MDC, to:

lista zer lub więcej par nazw właściwości i powiązanych wartości obiektu, ujęta w nawiasy klamrowe ({}).

Dlatego dosłowny obiekt nie jest tablicą i można uzyskać dostęp do właściwości tylko za pomocą ich jawnej nazwy lub forpętli za pomocą insłowa kluczowego.

Alex Różański
źródło
25
Dla innych widzących tylko zielony znaczek na tej odpowiedzi, istnieje inne rozwiązanie na dole strony z obecnie 350 głosami pozytywnymi.
redfox05
7

Najlepsza odpowiedź może wygenerować całą tablicę, a następnie przechwycić z listy. Oto kolejny skuteczny skrót

var obj = { first: 'someVal' };
Object.entries(obj)[0][1] // someVal
kishorekumaru
źródło
3

Zostało to tutaj omówione wcześniej.

Pojęcie pierwszego nie dotyczy właściwości obiektu, a specyfikacja nie gwarantuje kolejności pętli for ... in, jednak w praktyce jest to niezawodnie FIFO, z wyjątkiem krytycznie dla chrome ( raport o błędach ). Podejmij odpowiednie decyzje.

annakata
źródło
3

Nie polecam używać Object.keys, ponieważ nie jest obsługiwany w starych wersjach IE. Ale jeśli naprawdę tego potrzebujesz, możesz użyć powyższego kodu, aby zagwarantować kompatybilność wsteczną:

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;
}})()};

Funkcja Firefox (Gecko) 4 (2.0) Chrome 5 Internet Explorer 9 Opera 12 Safari 5

Więcej informacji: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

Ale jeśli potrzebujesz tylko pierwszego, możemy zaproponować krótsze rozwiązanie, takie jak:

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
źródło
2

Aby uzyskać pierwszą nazwę klucza w obiekcie, możesz użyć:

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

Zwraca ciąg znaków, więc nie można uzyskać dostępu do zagnieżdżonych obiektów, jeśli takie istnieją:

var obj = { first: { someVal : { id : 1} }; W tym rozwiązaniu nie można uzyskać dostępu do identyfikatora.

Najlepszym rozwiązaniem, jeśli chcesz uzyskać rzeczywisty obiekt, jest lodash:

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

Aby zwrócić wartość pierwszego klucza (jeśli nie znasz dokładnie nazwy pierwszego klucza):

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

jeśli znasz nazwę klucza, użyj:

obj.first

lub

obj['first']
Diego Unanue
źródło
0

Jeśli potrzebujesz uzyskać dostęp do „pierwszej właściwości obiektu”, może to oznaczać, że coś jest nie tak z twoją logiką. Kolejność właściwości obiektu nie powinna mieć znaczenia.

Flavius ​​Stef
źródło
Masz rację. Nie potrzebuję pierwszej, per se, ale tylko jednej właściwości foo, aby móc z nią pracować. Potrzebuję tylko jednego i nie byłem pewien, czy istnieje sposób, aby po prostu złapać „pierwszy” bez użycia dla ... w.
Google
0

Użyj tablicy zamiast obiektu (nawiasy kwadratowe).

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

Pamiętaj, że tracisz identyfikatory „foo”. Ale możesz dodać właściwość name do zawartych obiektów:

var example = [ 
  {name: 'foo1', /* stuff1 */},
  {name: 'foo2', /* stuff2 */},
  {name: 'foo3', /* stuff3 */}
];
var whatWasFirst = example[0].name;
parowiec 25
źródło
są sytuacje, w których nie możemy. Zakładamy, że nie możemy zmienić faktu, że nie ma ich w tablicy
1mike12
1
Wydaje mi się, że warto nieco odepchnąć projekt od czytelników, którzy mogą kontrolować swój schemat JSON. Zasadniczo rozszerzam odpowiedź Flaviusa Stefa na kilka przykładów.
parowiec25
0

Czy jest jakiś powód, aby tego nie robić?

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

(3) ["foo1", "foo2", "foo3"]
jtr13
źródło
8
Ponieważ .map()istnieje tylko dla wbudowanych iteratorów
kano
0

Możesz użyć, Object.prototype.keysktóry zwraca wszystkie klucze obiektu w tej samej kolejności. Więc jeśli chcesz pierwszy obiekt, po prostu weź tę tablicę i użyj pierwszego elementu jako pożądanego klucza.

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
źródło
1
Odpowiadając na stare pytanie, twoja odpowiedź byłaby znacznie bardziej przydatna dla innych użytkowników StackOverflow, gdybyś podał kontekst wyjaśniający, w jaki sposób twoja odpowiedź pomaga, szczególnie w przypadku pytania, które ma już zaakceptowaną odpowiedź. Zobacz: Jak napisać dobrą odpowiedź .
David Buck
0

możemy również zrobić z tym approch.

var example = {
  foo1: { /* stuff1 */},
  foo2: { /* stuff2 */},
  foo3: { /* stuff3 */}
}; 
Object.entries(example)[0][1];
Salil Sharma
źródło
0

Oto czystszy sposób na zdobycie pierwszego klucza:

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
źródło
Ale dlaczego tablica dookoła [first] . Użytkownik nie poprosił o tablicę jako odpowiedź. Po co to robić, first = Object.keys(example)[0]co zrobi to samo bez konieczności zawijania odpowiedzi w tablicy. Dlaczego proszę o czystsze?
Michael Durrant
To zadanie
restrukturyzacji