Как получить доступ к первому свойству объекта Javascript?

611

Есть ли элегантный способ доступа к первому свойству объекта ...

  1. где вы не знаете название вашей недвижимости
  2. без использования цикла, как for .. inили JQuery's$.each

Например, мне нужно получить доступ к foo1объекту, не зная имени foo1:

var example = {
    foo1: { /* stuff1 */},
    foo2: { /* stuff2 */},
    foo3: { /* stuff3 */}
};
atogle
источник
1
вероятно, лучше сначала превратить его в массив
cregox

Ответы:

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

Используя это, вы можете получить доступ и к другим свойствам по индексам. Будьте внимательны! Object.keysвозврат заказа не гарантируется в соответствии с ECMAScript, однако неофициально это происходит во всех основных реализациях браузеров, пожалуйста, прочитайте https://stackoverflow.com/a/23202095 для подробностей об этом.

Гжегож Качан
источник
25
Вы говорите, что это не самый быстрый способ. Какой путь будет быстрее?
Т Нгуен
3
Это не очень эффективно, так как создает целый массив всех ключей объекта.
Эндрю Мао
9
@T Нгуен Я бы опубликовал это, если бы знал это :)
Grzegorz Kaczan
5
@DavChana - у вас неверно настроен тест. Блок шаблона всегда будет выполняться, и ваш блок 2 будет пустым, что означает, что первый результат представляет шаблон выполнения + блок1 , а второй результат представляет только шаблон . Вот правильный тест: http://jsben.ch/#/R9aLQ , показывающий, что они в значительной степени равны (запустите тест несколько раз).
myfunkyside
9
Я хотел бы, чтобы first()что-то подобное могло справиться с этим.
Fr0zenFyr
113

Попробуйте for … inцикл и остановитесь после первой итерации:

for (var prop in object) {
    // object[prop]
    break;
}
гумбо
источник
1
Я думаю, что это единственный вариант. Я не уверен, что вы гарантированно будете повторять свойства в предсказуемом / полезном порядке. То есть вы можете использовать foo1, но получить foo3. Если свойства пронумерованы, как в примере, вы можете выполнить сравнение строк, чтобы определить идентификатор, заканчивающийся на «1». С другой стороны, если основной задачей коллекции является ординальность, вам, вероятно, следует использовать массив вместо объекта.
Steamer25
2
Если кто-то еще обеспокоен порядком, большинство браузеров ведут себя предсказуемо: stackoverflow.com/questions/280713/…
Flash
6
вар проп; для (опоры в объекте) перерыва; // object [prop]
netiul
12
Старый ответ но. Вы можете проверить, принадлежит ли свойство объекту. например: for (..) {if (! obj.hasOwnProperty (prop)) continue; .... перемена; } на тот случай, если объект на самом деле пуст, он не пересекает прототип или что-то еще.
pgarciacamou
65

Вы также можете сделать Object.values(example)[0].

garrettmaring
источник
Это доступно не во всех браузерах, ссылаясь на stackoverflow.com/a/38748490/719689
AlxVallejo
1
Мне это нравится больше, чем Object.keys, потому что вы гарантированно получите первый товар.
TheStherSide
Обновление от 2019 года, я думаю , что это работает на большинстве браузеров для IE , кроме developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ppak10
47

Используется Object.keysдля получения массива свойств объекта. Пример:

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

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

Документация и кросс-браузерная прокладка предоставлены здесь . Пример его использования можно найти в другом из моих ответов здесь .

Изменить : для ясности, я просто хочу повторить то, что было правильно указано в других ответах: порядок ключей в объектах JavaScript не определен.

benekastah
источник
25

Версия с одним правилом:

var val = example[function() { for (var k in example) return k }()];
netiul
источник
2
Иногда это может быть рискованно использовать for inбез проверки, так hasOwnPropertyкак объект содержит другие нежелательные значения, добавленные к нему программным способом, так что вы можете получить нежелательный результат из этого фрагмента. Тот факт, что он короткий и аккуратный, не означает его оптимальную безопасность
Хавьер Кобос
24

Не существует "первого" свойства. Ключи объектов неупорядочены.

Если вы зациклите их с помощью for, (var foo in bar)вы получите их в некотором порядке, но это может измениться в будущем (особенно если вы добавите или удалите другие ключи).

Quentin
источник
Потрясающие. Я использовал объект для реализации карты, которая поддерживает порядок вставки. Это ломается, как только я удаляю значение, потому что следующая вставка заполняет пробел. :(
Дэвид Харкнесс
2
порядок ключ / значение должен сохраняться в более новых версиях JS
Александр Миллс
11

Решение с библиотекой lodash :

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

но нет никакой гарантии порядка внутреннего хранения свойств объекта, потому что это зависит от реализации виртуальной машины Java.

Почепцов
источник
2
Просто проверил это, и это не работает. Возвращает только значение, а не пару ключ / значение.
Крис Хейнс
2
В вопросе нет упоминания о том, что он должен возвращать пару ключ / значение, он просто запрашивает объект, и принятый ответ делает то же самое, что и эта функция lodash: он возвращает содержимое первого свойства. Это может не соответствовать вашим конкретным потребностям, но этот ответ является правильным на основе исходного вопроса.
Карм
Да, делает работу, полезно, когда вы знаете, что у вашего объекта будет только один дочерний объектvar object = { childIndex: { .. } }; var childObject = _.find(Object);
Раджа Хури
9

Нет. Объектный литерал, как определено MDC :

список из нуля или более пар имен свойств и связанных значений объекта, заключенных в фигурные скобки ({}).

Следовательно, литерал объекта не является массивом, и вы можете получить доступ к свойствам только с помощью их явного имени или forцикла с помощью inключевого слова.

Алекс Розанский
источник
25
Для других, которые видят только зеленую галочку в этом ответе, есть еще одно решение внизу страницы с 350 голосами против.
redfox05
7

Верхний ответ может генерировать весь массив, а затем захватывать из списка. Вот еще один эффективный ярлык

var obj = { first: 'someVal' };
Object.entries(obj)[0][1] // someVal
kishorekumaru
источник
3

Это было рассмотрено здесь раньше.

Концепция first не применяется к свойствам объекта, и порядок цикла for ... in не гарантируется спецификациями, однако на практике это надежно FIFO, за исключением критически важного для chrome ( отчет об ошибках ). Принимайте свои решения соответственно.

annakata
источник
3

Я не рекомендую вам использовать Object.keys, поскольку он не поддерживается в старых версиях IE. Но если вам это действительно нужно, вы можете использовать приведенный выше код, чтобы гарантировать обратную совместимость:

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

Особенность Firefox (Gecko) 4 (2.0) Chrome 5 Internet Explorer 9 Opera 12 Safari 5

Дополнительная информация: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

Но если вам нужен только первый, мы могли бы предложить более короткое решение, например:

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"}
Хавьер Кобос
источник
2

Чтобы получить первое имя ключа в объекте, вы можете использовать:

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

Возвращает строку, поэтому вы не можете получить доступ к вложенным объектам, если они есть, например:

var obj = { first: { someVal : { id : 1} }; Здесь с этим решением вы не можете получить доступ к идентификатору.

Лучшее решение, если вы хотите получить реальный объект, это использовать lodash, например:

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

Чтобы вернуть значение первого ключа (если вы не знаете точно имя первого ключа):

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

если вы знаете имя ключа, просто используйте:

obj.first

или

obj['first']
Диего Унануэ
источник
0

Если вам нужен доступ к «первому свойству объекта», это может означать, что с вашей логикой что-то не так. Порядок свойств объекта не должен иметь значения.

Флавиус Стеф
источник
Вы правы. Мне не нужен первый, как таковой, но только одно из свойств foo, чтобы я мог с ним работать. Мне нужен только один, и я не был уверен, есть ли способ просто взять «первый», не используя for… in.
atogle
0

Используйте массив вместо объекта (квадратные скобки).

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

Обратите внимание, что вы теряете идентификаторы 'foo'. Но вы можете добавить свойство name к содержащимся объектам:

var example = [ 
  {name: 'foo1', /* stuff1 */},
  {name: 'foo2', /* stuff2 */},
  {name: 'foo3', /* stuff3 */}
];
var whatWasFirst = example[0].name;
steamer25
источник
Есть ситуации, в которых мы не можем. Мы предполагаем, что не можем изменить тот факт, что они не в массиве
1mike12
1
Я думаю, что полезно немного отодвинуть дизайн для читателей, которые могут управлять своей схемой JSON. По сути, я расширяю ответ Флавиуса Стефа несколькими примерами.
steamer25
0

Вы можете использовать Object.prototype.keysкоторый возвращает все ключи объекта в том же порядке. Поэтому, если вы хотите первый объект, просто получите этот массив и используйте первый элемент в качестве желаемого ключа.

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
акаш кумар
источник
1
При ответе на старый вопрос ваш ответ был бы гораздо более полезным для других пользователей StackOverflow, если бы вы включили некоторый контекст для объяснения того, как ваш ответ помогает, особенно для вопроса, на который уже есть принятый ответ. Смотрите: Как мне написать хороший ответ .
Дэвид Бак
0

мы также можем сделать с этим подходом.

var example = {
  foo1: { /* stuff1 */},
  foo2: { /* stuff2 */},
  foo3: { /* stuff3 */}
}; 
Object.entries(example)[0][1];
Салил Шарма
источник
0

Вот более чистый способ получения первого ключа:

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]}`)

Нтийо Рихоцо
источник
Но почему массив вокруг [first]. Пользователь не запросил массив в качестве ответа. Зачем делать то, first = Object.keys(example)[0]что будет делать то же самое без необходимости заключать ответ в массив. Почему ваш чище, пожалуйста?
Майкл Даррант
Это деструктурирующее задание developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Нтийо Рихотсо