Как найти ключи хеша?


192

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

var h = {a:'b',c:'d'};

Я хочу что-то вроде

var k = h.keys() ; // k = ['a','c'];

Легко написать саму функцию для перебора элементов и добавления ключей в массив, который я возвращаю, но есть ли стандартный более чистый способ сделать это?

Я продолжаю чувствовать, что это должна быть простая встроенная функция, которую я пропустил, но я не могу ее найти!


Я просто прыгаю в javascript, но этот пост может вам помочь. dean.edwards.name/weblog/2006/07/enum
Джейсон Сальдо

Возможная
копия

1
Как насчет получения значений из ключей? Также получаем количество ключей в хэше.
zero_cool

Ответ на 2017 год: Object.keys (h) Object.values ​​(h)
проигрыш

Ответы:


274

В современном JavaScript (ECMAScript 5) есть функция, которая Object.keysвыполняет эту операцию:

var obj = { "a" : 1, "b" : 2, "c" : 3};
alert(Object.keys(obj)); // will output ["a", "b", "c"]

Подробности о совместимости можно найти здесь .

На сайте Mozilla также есть фрагмент обратной совместимости:

if(!Object.keys) Object.keys = function(o){
   if (o !== Object(o))
      throw new TypeError('Object.keys called on non-object');
   var ret=[],p;
   for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
   return ret;
}

разве это не было бы более естественным? if(!Object.prototype.keys) Object.prototype.keys = function() { if (this !== Object(this)) throw new TypeError('Object.keys called on non-object'); var ret = [], p; for (p in this) if (Object.prototype.hasOwnProperty.call(this, p)) ret.push(p); return ret; } var x = { a: { A: 1, B: 2, C: 3 }, b: { A: 10, B: 20 } }; alert(x.a.keys());
ekkis

2
Как я понимаю, это Object.prototype.keysсделает keysдоступным для всех подклассов объекта, следовательно, для всех объектов. Что, вероятно, вы хотите, если вы пытаетесь использовать ООП. В любом случае это действительно зависит от ваших требований.
Иван Невоструев

1
Если вы используете mootools, Object.keys () должен быть доступен во всех браузерах.
Thepeer

Есть ли что-нибудь, чтобы использовать это в угловых шаблонах? Это не работает там внутри частичных.
Джей Шукла

Я думаю, что вы должны задать это как отдельный вопрос с примером кода.
Иван Невоструев

80

Для производственного кода, требующего большой совместимости с клиентскими браузерами, я все же предлагаю ответ Ивана Невоструева, приведенный выше, с шимом, чтобы убедиться Object.keysв старых браузерах. Тем не менее, можно получить точную функциональность, запрошенную с помощью новой definePropertyфункции ECMA .

Начиная с ECMAScript 5 - Object.defineProperty

Начиная с ECMA5 вы можете использовать Object.defineProperty()для определения не перечисляемых свойств. Тока совместимость до сих пор желать лучшего, но это должно в конечном итоге стать полезной во всех браузерах. (Обратите особое внимание на текущую несовместимость с IE8!)

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    var keys = [];
    for(var i in this) if (this.hasOwnProperty(i)) {
      keys.push(i);
    }
    return keys;
  },
  enumerable: false
});

var o = {
    'a': 1,
    'b': 2
}

for (var k in o) {
    console.log(k, o[k])
}

console.log(o.keys())

# OUTPUT
# > a 1
# > b 2
# > ["a", "b"]

Однако, так как ECMA5 уже добавлен, Object.keysвы также можете использовать:

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    return Object.keys(this);
  },
  enumerable: false
});

Оригинальный ответ

Object.prototype.keys = function ()
{
  var keys = [];
  for(var i in this) if (this.hasOwnProperty(i))
  {
    keys.push(i);
  }
  return keys;
}

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

Нет никакого способа сделать функции-прототипы не перечисляемыми, что приводит к их постоянному включению в циклы for-in, которые не используются hasOwnProperty. Я все еще думаю, что этот ответ был бы идеальным, если бы расширение прототипа Object не было таким грязным.


9
'hasOwnProperty' исключает свойства прототипов этого объекта, что полезно знать.
ijw

2
Ответ принят, потому что так я его реализовал, но я чувствую, что это должно было быть встроенной функцией языка.
Пэт

5
Обратите внимание, что вы должны использовать «for (var i in this) ...», чтобы избежать создания глобальной переменной.
Брэд Г.

5
Я бы не стал изменять Object.prototype - как заметил другой комментатор ниже, это может легко сломать скрипты, которые не заботятся о проверке hasOwnProperty (). Вместо этого используйте менее дружественный к OO способ: определите функцию «keys», если она еще не существует. (Firefox и Chrome оба реализуют встроенную функцию keys (), которая делает именно то, что хочет OP, а IE нет)
digitalbath

1
Кажется плохой идеей добавить что-либо в Object.prototype, так как он прерывает каждый нормальный цикл, например: for (var k в массиве) {} или for (var k в объекте), и эта идиома - хотя это может быть ошибочно - чрезвычайно распространено. Например, согласно ответу Мэтью Дарвина ниже, это нарушает Google Maps.
Сэм Уоткинс

42

ты можешь использовать Object.keys

Object.keys(h)

3
Добавлен в ECMAScript 5, но к настоящему времени должен работать в большинстве основных браузеров
Pat

33

Вы можете использовать Underscore.js , который является утилитарной библиотекой Javascript.

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

Ну, это не совсем то, о чем спрашивали, потому что @Pat ищет встроенную функцию, но тем не менее это интересная библиотека, и она не модифицируетсяObject.prototype
fresskoma

2
Сегодня я думаю, что гораздо полезнее использовать эти изящные маленькие библиотеки, чем писать собственные реализации ... В любом случае, в большинстве реальных проектов мы в любом случае используем Underscore или эквивалентные библиотеки. Лично я предпочел бы пойти с Underscore.
kumarharsh

_.keys(obj).lengthчтобы увидеть, есть ли какие-либо ключи.
Чови

13

Это лучшее, что вы можете сделать, насколько я знаю ...

var keys = [];
for (var k in h)keys.push(k);

2
Это также не работает, когда Object.prototype был испорчен.
Фил

4
Было бы лучше использовать это, а не "связываться с" Object.prototype. Кажется, что все ломается, если мы добавляем вещи в Object.prototype: это чрезвычайно распространенная идиома для циклического перебора ключей массива / объекта.
Сэм Уоткинс

8

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

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
var keys = [];
$.each(bobject, function(key,val){ keys.push(key); });
console.log(keys); // ["primary", "bg", "hilite"]

Или:

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
$.map(bobject, function(v,k){return k;});

благодаря @pimlottc


3
Если вы хотите пойти по этому пути, вы можете также использовать JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc

6

Я считаю, что вы можете просмотреть свойства объекта с помощью for / in, чтобы вы могли сделать что-то вроде этого:

function getKeys(h) {
  Array keys = new Array();
  for (var key in h)
    keys.push(key);
  return keys;
}

4

Я хотел использовать ответ с самым высоким рейтингом выше

Object.prototype.keys = function () ...

Однако при использовании вместе с API карт Google v3 карты Google не работают.

for (var key in h) ...

работает хорошо.


1

если вы пытаетесь получить только элементы, но не функции, тогда этот код может помочь вам

this.getKeys = function() {

var keys = new Array();
for(var key in this) {

    if( typeof this[key] !== 'function') {

        keys.push(key);
    }
}
return keys;

}

это часть моей реализации HashMap, и я хочу только ключи, thisэто объект hashmap, который содержит ключи

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.