Jak znaleźć klucze skrótu?


192

Znam w javascript Objects podwójnie jako skróty, ale nie byłem w stanie znaleźć wbudowanej funkcji, aby uzyskać klucze

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

Chcę coś takiego

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

Łatwo jest napisać funkcję, aby iterować elementy i dodać klucze do tablicy, którą zwracam, ale czy istnieje standardowy, czystszy sposób, aby to zrobić?

Wciąż czuję, że musi to być prosta wbudowana funkcja, za którą tęskniłem, ale nie mogę jej znaleźć!


Właśnie wskakuję do javascript, ale ten post może ci pomóc. dean.edwards.name/weblog/2006/07/enum
jason saldo


1
Co z uzyskaniem wartości z kluczy? Również uzyskiwanie liczby kluczy w haszu.
zero_cool

Odpowiedź z 2017 r .: Object.keys (h) Object.values ​​(h)
losty

Odpowiedzi:


274

We współczesnym JavaScript (ECMAScript 5) istnieje funkcja nazywana Object.keyswykonywaniem tej operacji:

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

Szczegóły kompatybilności można znaleźć tutaj .

Na stronie Mozilli znajduje się także fragment dla kompatybilności wstecznej:

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

czy nie byłoby to bardziej naturalne? 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
Jak rozumiem Object.prototype.keys, keysudostępni to wszystkim podklasom Object, a zatem wszystkim obiektom. Które prawdopodobnie chcesz, jeśli próbujesz użyć OOP. W każdym razie tak naprawdę zależy to od twoich wymagań.
Ivan Nevostruev

1
Jeśli używasz mootools, Object.keys () powinien być dostępny we wszystkich przeglądarkach.
thepeer

Czy jest coś takiego w szablonach kątowych? Nie działa tam w częściach cząstkowych.
Jay Shukla,

Myślę, że powinieneś zadać to jako osobne pytanie z próbką kodu.
Ivan Nevostruev

80

W przypadku kodu produkcyjnego wymagającego dużej kompatybilności z przeglądarkami klienckimi nadal sugeruję powyższą odpowiedź Iwana Nevostrueva, aby upewnić się Object.keysw starszych przeglądarkach. Możliwe jest jednak uzyskanie dokładnej żądanej funkcjonalności za pomocą nowej wersji ECMAdefineProperty funkcji .

Od ECMAScript 5 - Object.defineProperty

Od ECMA5 można używać Object.defineProperty()do definiowania właściwości niepoliczalnych . Prąd kompatybilność nadal ma wiele do życzenia, ale to powinno ostatecznie stać się użyteczna we wszystkich przeglądarkach. (Zwłaszcza zwróć uwagę na obecną niezgodność z 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"]

Ponieważ jednak dodano już ECMA5 Object.keys, równie dobrze możesz użyć:

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

Oryginalna odpowiedź

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

Edytować: Ponieważ ta odpowiedź już istnieje, pozostawię powyższe nietknięte. Każdy, kto to czyta, powinien również przeczytać poniżej odpowiedź Iwana Nevostrueva.

Nie ma sposobu, aby funkcje prototypowe były niepoliczalne, co powoduje, że zawsze pojawiają się w pętlach wejściowych, które nie są używane hasOwnProperty. Nadal uważam, że ta odpowiedź byłaby idealna, gdyby rozbudowa prototypu Object nie była taka niechlujna.


9
„hasOwnProperty” wyklucza właściwości prototypów tego obiektu, co warto wiedzieć.
ijw

2
Odpowiedź została zaakceptowana, ponieważ w ten sposób ostatecznie ją wdrożyłem, ale uważam, że powinna to być wbudowana funkcja języka.
Pat

5
Zauważ, że powinieneś użyć „for (var i in this) ...”, aby uniknąć tworzenia zmiennej globalnej.
Brad G.

5
Unikałbym modyfikowania Object.prototype - jak zauważył inny komentator poniżej, może to łatwo złamać skrypty, które nie są ostrożne w sprawdzaniu hasOwnProperty (). Zamiast tego użyj mniej przyjaznego dla OO sposobu: zdefiniuj funkcję „klawiszy”, jeśli jeszcze nie istnieje. (Zarówno Firefox, jak i Chrome implementują funkcję natywnych klawiszy (), która robi dokładnie to, czego chce OP - IE tego nie robi)
digitalbath

1
Wydaje się, że złym pomysłem jest dodanie czegokolwiek do Object.prototype, ponieważ przerywa każdą normalną pętlę, np .: for (var k in array) {} lub for (var k in object), i ten idiom - choć może być wadliwy - jest niezwykle powszechny. Na przykład, zgodnie z odpowiedzią Matthew Darwina poniżej, psuje Mapy Google.
Sam Watkins,

42

możesz użyć Object.keys

Object.keys(h)

3
Dodano w ECMAScript 5, ale do tej pory powinno działać w większości głównych przeglądarek
Pat

33

Możesz użyć Underscore.js , który jest biblioteką narzędzi JavaScript.

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

Cóż, to nie jest tak naprawdę to, o co pytano, ponieważ @Pat szuka wbudowanej funkcji, ale mimo to jest interesującą biblioteką i nie można jej modyfikowaćObject.prototype
fresskoma

2
W dzisiejszych czasach myślę, że o wiele bardziej pomocne jest używanie tych sprytnych małych bibliotek - niż pisanie własnych implementacji ... W każdym razie, w większości rzeczywistych projektów, i tak używamy Underscore lub równoważnych bibliotek. Osobiście wolałbym używać Underscore.
kumarharsh

_.keys(obj).lengthaby sprawdzić, czy są jakieś klucze.
chovy

13

O ile wiem, to najlepsze, co możesz zrobić ...

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

2
To również nie działa, gdy pomylono Object.prototype.
Phil

4
Lepiej byłoby użyć tego, a nie „zadzierać” z Object.prototype. Wygląda na to, że wszystko się psuje, jeśli dodamy coś do Object.prototype: niezwykle powszechnym idiomem jest zapętlanie klawiszy tablicy / obiektu.
Sam Watkins

8

Za pomocą jQuery możesz uzyskać następujące klucze:

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

Lub:

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

dzięki @pimlottc


3
Jeśli chcesz jechać tą drogą, równie dobrze możesz użyć JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc

6

Wierzę, że możesz przeglądać właściwości obiektu za pomocą for / in, więc możesz zrobić coś takiego:

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

4

Chciałem użyć wyżej ocenianej odpowiedzi

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

Jednak w przypadku korzystania w połączeniu z Google Maps API v3 mapy google nie działają.

for (var key in h) ...

działa dobrze.


1

jeśli próbujesz uzyskać tylko elementy, ale nie funkcje, ten kod może ci pomóc

this.getKeys = function() {

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

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

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

}

jest to część mojej implementacji HashMap i chcę tylko kluczy, thisto obiekt hashmap, który zawiera klucze

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.