Як знайти ключі хеша?


192

Я знаю, що в JavaScript об’єкти подвоюються як хеші, але мені не вдалося знайти вбудовану функцію, щоб отримати ключі

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

Я хочу щось подібне

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

Просто написати функцію, щоб перебрати елементи та додати ключі до масиву, який я повертаю, але чи є стандартний чистіший спосіб зробити це?

Я відчуваю, що це повинна бути проста вбудована функція, яку я пропустив, але я не можу її знайти!


Я просто стрибаю в JavaScript, але ця публікація може вам допомогти. dean.edwards.name/weblog/2006/07/enum
Джейсон SALDO

Можливий дублікат Get масиву ключів об’єкта
blo0p3r

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доступним для всіх підкласів Object, отже, для всіх об’єктів. Що, напевно, ви хочете, якщо ви намагаєтесь використовувати OOP. У будь-якому випадку це дійсно залежить від ваших вимог.
Іван Невоструєв

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

Редагувати: Оскільки ця відповідь існує деякий час, я залишаю недоторканим вище. Кожен, хто читає це, також повинен прочитати відповідь Івана Невоструєва нижче.

Немає можливості зробити прототипні функції незліченними, що призводить до того, що вони завжди з'являються у циклі для введення, які не використовуються hasOwnProperty. Я все ще думаю, що ця відповідь була б ідеальною, якби розширення прототипу Об’єкта було не таким безладним.


9
'hasOwnProperty' виключає властивості прототипів цього об’єкта, про що корисно знати.
ijw

2
Відповідь прийнято, тому що я закінчив її реалізацію, але я вважаю, що це повинна бути вбудованою функцією мови.
Пат

5
Зауважте, що вам слід використовувати "for (var i in this) ...", щоб уникнути створення глобальної змінної.
Бред Г.

5
Я б уникнув модифікації Object.prototype - як зазначив інший коментатор нижче, це може легко зламати скрипти, які не уважно ставляться до перевірки hasOwnProperty (). Натомість скористайтеся менш зручним для OO способом: визначте функцію "клавіш", якщо вона ще не існує. (Firefox та Chrome реалізують функцію нативної клавіші (), яка робить саме те, що хоче ОП - IE не робить)
digitalbath

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

42

ви можете використовувати Object.keys

Object.keys(h)

3
Додано в ECMAScript 5, але до теперішнього часу він повинен працювати в більшості основних браузерів
пат

33

Ви можете використовувати Underscore.js , що є бібліотекою утиліт Javascript.

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

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

2
У цей час я думаю, що набагато корисніше використовувати ці витончені маленькі бібліотеки, ніж продовжувати писати власні реалізації ... У будь-якому випадку в більшості реальних проектів ми все одно використовуємо підкреслення або подібні бібліотеки. Особисто я вважаю за краще піти з підкресленням.
кумархарш

_.keys(obj).lengthщоб побачити, чи є якісь клавіші.
chovy

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

Я вважаю, що ви можете переглядати властивості об'єкта, використовуючи для / в, щоб ви могли зробити щось подібне:

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

4

Я хотів використати вищезазначену відповідь

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

Однак при використанні спільно з API google maps 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це об’єкт хешмапу, який містить ключі

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.