Làm thế nào để tìm khóa của hàm băm?


192

Tôi biết trong các đối tượng javascript gấp đôi số băm nhưng tôi không thể tìm thấy hàm dựng sẵn để lấy các khóa

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

Tôi muốn một cái gì đó như

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

Thật đơn giản để tự viết một hàm để lặp lại các mục và thêm các khóa vào một mảng mà tôi trả về, nhưng có cách nào sạch hơn để làm điều đó không?

Tôi luôn cảm thấy nó phải là một chức năng được xây dựng đơn giản mà tôi đã bỏ lỡ nhưng tôi không thể tìm thấy nó!


Tôi chỉ nhảy vào javascript nhưng bài đăng này có thể giúp bạn. dean.edwards.name/weblog/2006/07/enum
jason saldo


1
Điều gì về việc nhận được các giá trị từ các phím? Ngoài ra, nhận được số lượng khóa trong một hàm băm.
zero_cool

Câu trả lời năm 2017: Object.keys (h) Object.values ​​(h)
mất

Câu trả lời:


274

Có chức năng trong JavaScript hiện đại (ECMAScript 5) được gọi là Object.keysthực hiện thao tác này:

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

Chi tiết tương thích có thể được tìm thấy ở đây .

Trên trang Mozilla cũng có một đoạn để tương thích ngược:

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

điều này sẽ được tự nhiên hơn? 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
Theo tôi hiểu, điều này Object.prototype.keyssẽ làm keyscho tất cả các lớp con của Object, do đó cho tất cả các đối tượng. Mà có lẽ bạn muốn nếu bạn đang cố gắng sử dụng OOP. Dù sao điều này thực sự phụ thuộc vào yêu cầu của bạn.
Ivan Nevostruev

1
Nếu bạn sử dụng mootools, Object.keys () sẽ có sẵn trong tất cả các trình duyệt.
thepeer

Có bất cứ điều gì để sử dụng này trong các mẫu góc? Nó không hoạt động ở đó bên trong partials.
Jay Shukla

Tôi nghĩ bạn nên hỏi điều này như một câu hỏi riêng biệt với mẫu mã.
Ivan Nevostruev

80

Đối với mã sản xuất yêu cầu khả năng tương thích lớn với các trình duyệt máy khách, tôi vẫn đề xuất câu trả lời của Ivan Nevostruev ở trên với shim để đảm bảo Object.keystrong các trình duyệt cũ hơn. Tuy nhiên, có thể nhận được chức năng chính xác được yêu cầu bằng definePropertytính năng mới của ECMA .

Kể từ ECMAScript 5 - Object.defineProperty

Kể từ ECMA5, bạn có thể sử dụng Object.defineProperty()để xác định các thuộc tính không thể đếm được. Khả năng tương thích hiện tại vẫn còn nhiều điều mong muốn, nhưng điều này cuối cùng sẽ trở nên có thể sử dụng được trong tất cả các trình duyệt. (Cụ thể lưu ý sự không tương thích hiện tại với 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"]

Tuy nhiên, vì ECMA5 đã được thêm, Object.keysbạn cũng có thể sử dụng:

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

Câu trả lời gốc

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

Chỉnh sửa: Vì câu trả lời này đã xuất hiện được một thời gian nên tôi sẽ không nói đến những điều trên. Bất cứ ai đọc điều này cũng nên đọc câu trả lời của Ivan Nevostruev dưới đây.

Không có cách nào để làm cho các hàm nguyên mẫu không thể đếm được, điều này dẫn đến chúng luôn luôn xuất hiện trong các vòng lặp for-in không sử dụng hasOwnProperty. Tôi vẫn nghĩ câu trả lời này sẽ rất lý tưởng nếu việc mở rộng nguyên mẫu của Object không quá lộn xộn.


9
'hasOwnProperty' loại trừ các thuộc tính trên các nguyên mẫu của đối tượng này, rất hữu ích để biết.
ijw

2
Câu trả lời được chấp nhận vì đó là cách tôi kết thúc việc thực hiện nó nhưng tôi cảm thấy đây nên là một chức năng tích hợp của ngôn ngữ.
Pat

5
Lưu ý rằng bạn nên sử dụng "for (var i in this) ..." để tránh tạo biến toàn cục.
Brad G.

5
Tôi sẽ tránh sửa đổi Object.prototype - như một nhà bình luận khác đã lưu ý bên dưới, điều này có thể dễ dàng phá vỡ các tập lệnh không cẩn thận khi kiểm tra hasOwnProperty (). Thay vào đó, hãy sử dụng cách ít thân thiện với OO hơn: xác định chức năng 'phím' nếu nó không tồn tại. (Cả Firefox và Chrome đều thực hiện chức năng khóa gốc () thực hiện chính xác những gì OP muốn - IE không)
digitalbath

1
Có vẻ là một ý tưởng tồi khi thêm bất cứ thứ gì vào Object.prototype, vì nó phá vỡ mọi vòng lặp thông thường như: for (var k in mảng) {} hoặc for (var k in object) và thành ngữ đó - mặc dù nó có thể bị lỗi - là cực kỳ phổ biến. Ví dụ, theo câu trả lời của Matthew Darwin bên dưới, nó phá vỡ Google Maps.
Sam Watkins

42

bạn có thể dùng Object.keys

Object.keys(h)

3
Đã thêm vào ECMAScript 5 nhưng sẽ hoạt động trong hầu hết các trình duyệt chính vào lúc này
Pat

33

Bạn có thể sử dụng Underscore.js , đây là một thư viện tiện ích Javascript.

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

Chà, đó thực sự không phải là những gì được hỏi, bởi vì @Pat đang tìm kiếm một chức năng tích hợp, nhưng dù sao đó cũng là một thư viện thú vị và nó không sửa đổiObject.prototype
fresskoma

2
Ngày nay, tôi nghĩ sẽ hữu ích hơn nhiều khi sử dụng những thư viện nhỏ bé tiện lợi này hơn là tiếp tục viết các triển khai của riêng bạn ... Dù sao, trong hầu hết các dự án trong thế giới thực, chúng tôi đều sử dụng thư viện Underscore hoặc tương đương. Cá nhân, tôi thích đi với Underscore.
kumarharsh

_.keys(obj).lengthđể xem nếu có bất kỳ phím.
chovy

13

Đây là điều tốt nhất bạn có thể làm, theo như tôi biết ...

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

2
Điều này cũng không hoạt động khi Object.prototype đã bị rối tung.
Phil

4
Sẽ tốt hơn nếu sử dụng cái này và không "gây rối" với Object.prototype. Dường như mọi thứ đều bị phá vỡ nếu chúng ta thêm mọi thứ vào Object.prototype: đó là một thành ngữ cực kỳ phổ biến để lặp qua các khóa của một mảng / đối tượng.
Sam Watkins

8

bằng cách sử dụng jQuery, bạn có thể nhận được các khóa như thế này:

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

Hoặc là:

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

cảm ơn @pimlottc


3
Nếu bạn muốn đi theo con đường này, bạn cũng có thể sử dụng JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc

6

Tôi tin rằng bạn có thể lặp qua các thuộc tính của đối tượng bằng cách sử dụng for / in, vì vậy bạn có thể làm một cái gì đó như thế này:

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

4

Tôi muốn sử dụng câu trả lời đánh giá hàng đầu ở trên

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

Tuy nhiên, khi sử dụng kết hợp với google maps API v3, google maps không hoạt động.

for (var key in h) ...

hoạt động tốt


1

nếu bạn đang cố gắng chỉ lấy các phần tử nhưng không phải các hàm thì mã này có thể giúp bạn

this.getKeys = function() {

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

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

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

}

đây là một phần trong quá trình triển khai HashMap của tôi và tôi chỉ muốn các khóa, thislà đối tượng hashmap chứa các khóa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.