วิธีการหากุญแจของกัญชา?


192

ฉันรู้ใน javascript Objects เป็นสองเท่าของแฮช แต่ฉันไม่สามารถหาฟังก์ชั่นในตัวเพื่อรับกุญแจได้

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

ฉันต้องการบางสิ่งบางอย่าง

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

มันง่ายที่จะเขียนฟังก์ชั่นของตัวเองเพื่อวนซ้ำไอเท็มและเพิ่มคีย์ไปยังอาเรย์ที่ฉันกลับมา แต่มีวิธีทำความสะอาดมาตรฐานที่จะทำเช่นนั้นหรือไม่?

ฉันรู้สึกว่ามันคงเป็นฟังก์ชั่นที่เรียบง่ายที่ฉันพลาดไป แต่ฉันหามันไม่เจอ!


ฉันแค่กระโดดเข้าจาวาสคริปต์ แต่โพสต์นี้อาจช่วยคุณได้ dean.edwards.name/weblog/2006/07/enum
jason

เป็นไปได้ที่ซ้ำกันของGet array ของกุญแจของวัตถุ
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 อย่างไรก็ตามเรื่องนี้ขึ้นอยู่กับความต้องการของคุณ
Ivan Nevostruev

1
หากคุณใช้ mootools ควรจะมี Object.keys () ในเบราว์เซอร์ทั้งหมด
thepeer

มีสิ่งใดบ้างที่จะใช้สิ่งนี้ในเทมเพลตเชิงมุม? มันไม่ทำงานที่นั่นภายในงาน
Jay Shukla

ฉันคิดว่าคุณควรถามคำถามนี้เป็นคำถามแยกต่างหากพร้อมตัวอย่างโค้ด
Ivan Nevostruev

80

สำหรับรหัสการผลิตที่ต้องการความเข้ากันได้กับเบราว์เซอร์ไคลเอนต์ฉันยังแนะนำคำตอบของ Ivan Nevostruev ด้านบนด้วย shim เพื่อให้แน่ใจObject.keysในเบราว์เซอร์รุ่นเก่า อย่างไรก็ตามเป็นไปได้ที่จะได้รับฟังก์ชั่นที่ต้องการโดยใช้ ECMA ใหม่definePropertyคุณสมบัติ

ในฐานะของ 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;
}

แก้ไข:เนื่องจากคำตอบนี้ผ่านไประยะหนึ่งแล้วฉันจะไม่ไปแตะข้างบน ทุกคนที่อ่านสิ่งนี้ควรอ่านคำตอบของ Ivan Nevostruev ด้านล่าง

มีวิธีการทำหน้าที่เป็นต้นแบบที่ไม่นับที่นำไปสู่พวกเขามักจะเปิดขึ้นใน-Fi hasOwnPropertyในลูปไม่มีที่ไม่ได้ใช้เป็น ฉันยังคิดว่าคำตอบนี้จะเหมาะถ้าการขยายต้นแบบของ Object ไม่ยุ่งเหยิง


9
'hasOwnProperty' ไม่รวมคุณสมบัติบนต้นแบบของวัตถุนี้ซึ่งมีประโยชน์ที่จะรู้
ijw

2
ยอมรับคำตอบเพราะนั่นคือวิธีที่ฉันลงเอยด้วยการนำมาใช้ แต่ฉันรู้สึกว่านี่น่าจะเป็นฟังก์ชั่นของภาษาในตัว
Pat

5
โปรดทราบว่าคุณควรใช้ "for (var i ในสิ่งนี้) ... " เพื่อหลีกเลี่ยงการสร้างตัวแปรกลาง
แบรดจี

5
ฉันจะหลีกเลี่ยงการแก้ไข Object.prototype - ตามที่ผู้แสดงความคิดเห็นคนอื่นบันทึกไว้ด้านล่างนี้สามารถทำลายสคริปต์ที่ไม่ระมัดระวังเกี่ยวกับการตรวจสอบ hasOwnProperty () ให้ใช้วิธีที่เป็นมิตรกับ OO น้อยกว่า: กำหนดฟังก์ชั่น 'keys' หากยังไม่มีอยู่ (Firefox และ Chrome ทั้งคู่ใช้ฟังก์ชั่นคีย์เนทีฟ () ซึ่งทำหน้าที่ตรงตามที่ OP ต้องการ - IE ไม่ได้)
digitalbath

1
ดูเหมือนว่าเป็นความคิดที่ดีที่จะเพิ่มสิ่งใด ๆ ลงใน Object.prototype เนื่องจากแบ่งทุกลูปปกติเช่น: สำหรับ (var k ในอาร์เรย์) {} หรือสำหรับ (var k ในวัตถุ) และสำนวนนั้น - แม้ว่ามันอาจจะผิดพลาด - เป็นเรื่องธรรมดามาก ตัวอย่างเช่นตามคำตอบของ Matthew Darwin ด้านล่างมันแบ่ง Google Maps
Sam Watkins

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 หรือไลบรารี่ที่เทียบเท่ากัน โดยส่วนตัวฉันอยากจะไปกับขีดล่าง
kumarharsh

_.keys(obj).lengthเพื่อดูว่ามีกุญแจหรือไม่
chovy

13

นี่คือสิ่งที่ดีที่สุดที่คุณสามารถทำได้เท่าที่ฉันรู้ ...

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

2
สิ่งนี้ยังใช้งานไม่ได้เมื่อ Object.prototype มีปัญหา
Phil

4
มันจะเป็นการดีกว่าถ้าใช้สิ่งนี้และอย่า "ยุ่งกับ" Object.prototype ดูเหมือนว่าทุกอย่างจะแตกถ้าเราเพิ่มสิ่งต่าง ๆ ลงใน Object.prototype: มันเป็นสำนวนที่ใช้กันทั่วไปมากในการวนลูปมากกว่าคีย์ของอาร์เรย์ / วัตถุ
Sam Watkins

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 () ...

อย่างไรก็ตามเมื่อใช้ร่วมกับ Google Maps API v3, Google Maps นั้นไม่สามารถใช้งานได้

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 ที่มีปุ่ม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.