วิธีรับค่าคุณสมบัติทั้งหมดของวัตถุ JavaScript (โดยไม่รู้ตัวกุญแจ)


455

หากมีวัตถุ Javascript:

var objects={...};

สมมติว่ามันมีคุณสมบัติมากกว่า 50 รายการโดยไม่ทราบชื่อคุณสมบัติ (นั่นคือโดยไม่รู้ตัว 'คีย์') วิธีรับค่าคุณสมบัติแต่ละค่าในลูป


23
หมายเหตุถึงผู้อ่าน: อย่าพลาดคำตอบที่สองที่
Pandaiolo

คำตอบ:


447

โดยใช้การfor..inวนรอบง่าย:

for(var key in objects) {
    var value = objects[key];
}

90
ระวังเกี่ยวกับคุณสมบัติของวัตถุต้นแบบที่ถูกสืบทอด ดู: hasOwnProperty ()
olive

102
หากคุณกำลังอ่านคำตอบนี้คุณควรอ่านอีกคนหนึ่งอย่างแน่นอน
การ์เซียเซีย

18
หากคุณกำลังอ่านคำตอบนี้และคุณอาจเกี่ยวข้องกับสตริงคุณควรเจาะจาวาสคริปต์ในหน้า

หากคุณอ่านคำตอบข้างต้นและต้องการที่จะชกต่อยจาวาสคริปต์ในหน้าลองLodash
slugmandrew

ควรชี้ให้เห็นว่าสิ่งนี้จะไม่รวมคุณสมบัติที่มีการenumerableตั้งค่าสถานะเป็นเท็จ สิ่งนี้หมายถึงคุณจะไม่ทำซ้ำในวิธีการเรียนใด ๆ แต่คุณจะทำซ้ำมากกว่าวิธีที่สร้างในวิธีอื่น
รวย remer

1012

ขึ้นอยู่กับเบราว์เซอร์ที่คุณต้องรองรับสิ่งนี้สามารถทำได้หลายวิธี ส่วนใหญ่ที่ครอบงำของเบราว์เซอร์ในการสนับสนุนป่า ECMAScript 5 (ES5) แต่ได้รับการเตือนว่าหลายตัวอย่างด้านล่างใช้Object.keysซึ่งไม่สามารถใช้ได้ใน IE < 9. เห็นตารางการทำงานร่วมกัน

ECMAScript 3+

หากคุณต้องรองรับ IE เวอร์ชันเก่ากว่านี้เป็นตัวเลือกสำหรับคุณ:

for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
        var val = obj[key];
        // use val
    }
}

ซ้อนกันifทำให้แน่ใจว่าคุณไม่ได้ระบุคุณสมบัติในห่วงโซ่ต้นแบบของวัตถุ (ซึ่งเป็นพฤติกรรมที่คุณต้องการได้อย่างแน่นอน) คุณต้องใช้

Object.prototype.hasOwnProperty.call(obj, key) // ok

ค่อนข้างมากกว่า

obj.hasOwnProperty(key) // bad

เนื่องจาก ECMAScript 5+ ช่วยให้คุณสามารถสร้างวัตถุต้นแบบด้วยObject.create(null)และวัตถุเหล่านี้จะไม่มีhasOwnPropertyวิธี รหัส Naughty อาจสร้างวัตถุที่แทนที่hasOwnPropertyวิธีการ

ECMAScript 5+

คุณสามารถใช้วิธีการเหล่านี้ในเบราว์เซอร์ที่รองรับ ECMAScript 5 ขึ้นไป สิ่งเหล่านี้จะได้รับค่าจากวัตถุและหลีกเลี่ยงการแจกแจงต้นแบบลูกโซ่ objวัตถุของคุณอยู่ที่ไหน:

var keys = Object.keys(obj);

for (var i = 0; i < keys.length; i++) {
    var val = obj[keys[i]];
    // use val
}

ถ้าคุณต้องการบางสิ่งที่เล็กกะทัดรัดกว่าหรือคุณต้องการระวังฟังก์ชั่นในลูปArray.prototype.forEachนั่นคือเพื่อนของคุณ:

Object.keys(obj).forEach(function (key) {
    var val = obj[key];
    // use val
});

วิธีการถัดไปจะสร้างอาร์เรย์ที่มีค่าของวัตถุ สะดวกสำหรับการวนซ้ำ

var vals = Object.keys(obj).map(function (key) {
    return obj[key];
});

// use vals array

หากคุณต้องการที่จะทำให้ผู้ที่ใช้Object.keysกับความปลอดภัยnull(ในฐานะfor-inเป็น) Object.keys(obj || {})...จากนั้นคุณสามารถทำได้

Object.keysส่งคืนคุณสมบัติที่นับได้ สำหรับการวนซ้ำวัตถุอย่างง่ายมักจะเพียงพอ ถ้าคุณมีบางสิ่งบางอย่างที่มีคุณสมบัติที่ไม่นับว่าคุณจะต้องทำงานร่วมกับคุณอาจจะใช้ในสถานที่ของObject.getOwnPropertyNamesObject.keys

ECMAScript 2015+ (AKA ES6)

อาร์เรย์ง่ายกว่าในการวนซ้ำกับ ECMAScript 2015 คุณสามารถใช้สิ่งนี้เพื่อประโยชน์ของคุณเมื่อทำงานกับค่าหนึ่งต่อหนึ่งในลูป:

for (const key of Object.keys(obj)) {
    const val = obj[key];
    // use val
}

การใช้ฟังก์ชั่นลูกศรอ้วน ECMAScript 2015 การจับคู่วัตถุกับอาร์เรย์ของค่าจะกลายเป็นหนึ่งซับ:

const vals = Object.keys(obj).map(key => obj[key]);

// use vals array

ECMAScript 2015 แนะนำSymbolอินสแตนซ์ซึ่งอาจใช้เป็นชื่อคุณสมบัติ ในการรับสัญลักษณ์ของวัตถุให้แจกแจงใช้Object.getOwnPropertySymbols(ฟังก์ชั่นนี้คือเหตุผลที่Symbol ไม่สามารถใช้เพื่อสร้างคุณสมบัติส่วนตัว) ReflectAPI ใหม่จาก ECMAScript 2015 จัดทำReflect.ownKeysขึ้นซึ่งจะส่งคืนรายการชื่อคุณสมบัติ (รวมถึงชื่อที่ไม่สามารถนับได้) และสัญลักษณ์

Array comprehensions (อย่าพยายามใช้)

ความเข้าใจในอาร์เรย์ถูกลบออกจาก ECMAScript 6 ก่อนที่จะเผยแพร่ ก่อนที่จะนำออกโซลูชันจะมีลักษณะดังนี้:

const vals = [for (key of Object.keys(obj)) obj[key]];

// use vals array

ECMAScript 2017+

ECMAScript 2016 เพิ่มคุณสมบัติที่ไม่ส่งผลกระทบต่อเรื่องนี้ ECMAScript 2017 สเปคเพิ่มและObject.values Object.entriesทั้งสองอาร์เรย์ส่งคืน (ซึ่งจะน่าแปลกใจที่บางคนได้รับการเปรียบเทียบกับArray.entries) Object.valuesสามารถใช้ตามสภาพที่เป็นหรือมีfor-ofลูป

const values = Object.values(obj);

// use values array or:

for (const val of Object.values(obj)) {
    // use val
}

หากคุณต้องการใช้ทั้งคีย์และค่าดังนั้นจึงObject.entriesเหมาะสำหรับคุณ มันผลิตอาร์เรย์ที่เต็มไปด้วย[key, value]คู่ คุณสามารถใช้สิ่งนี้ตามที่เป็นอยู่หรือ (โปรดทราบการมอบหมายการทำลายล้าง ECMAScript 2015) ในการfor-ofวนซ้ำ:

for (const [key, val] of Object.entries(obj)) {
    // use key and val
}

Object.values ชิม

ในที่สุดตามที่ระบุไว้ในความคิดเห็นและโดย teh_senaus ในคำตอบอื่นมันอาจจะคุ้มค่าโดยใช้อย่างใดอย่างหนึ่งเหล่านี้เป็นชิม ไม่ต้องกังวลต่อไปนี้จะไม่เปลี่ยนต้นแบบเพียงเพิ่มวิธีการObject(ซึ่งอันตรายน้อยกว่ามาก) การใช้ฟังก์ชั่นลูกศรไขมันสามารถทำได้ในหนึ่งบรรทัดด้วย:

Object.values = obj => Object.keys(obj).map(key => obj[key]);

ซึ่งตอนนี้คุณสามารถใช้เช่น

// ['one', 'two', 'three']
var values = Object.values({ a: 'one', b: 'two', c: 'three' });

หากคุณต้องการหลีกเลี่ยงการแรเงาเมื่อมีObject.valuesอยู่แล้วคุณสามารถทำได้:

Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]));

สุดท้าย ...

ระวังเบราว์เซอร์ / รุ่นที่คุณต้องการสนับสนุน ด้านบนถูกต้องเมื่อมีการใช้วิธีการหรือคุณสมบัติภาษา ตัวอย่างเช่นการสนับสนุน ECMAScript 2015 ถูกปิดใช้งานตามค่าเริ่มต้นใน V8 จนกระทั่งเมื่อไม่นานมานี้เบราว์เซอร์ที่ขับเคลื่อนเช่น Chrome ควรหลีกเลี่ยงฟีเจอร์จาก ECMAScript 2015 จนกว่าเบราว์เซอร์ที่คุณต้องการสนับสนุนจะใช้งานคุณสมบัติที่คุณต้องการ หากคุณใช้Babelเพื่อรวบรวมรหัสของคุณไปยัง ECMAScript 5 คุณจะสามารถเข้าถึงคุณสมบัติทั้งหมดในคำตอบนี้


9
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ (หรืออย่างน้อย upvoted เพิ่มเติม) เนื่องจากคำตอบที่ยอมรับนั้นไม่สมบูรณ์ (@olive points นี้)
0xc0de

เป็นความอัปยศที่กลอุบายที่เรียกว่าทั้งหมดเรายังต้องพูดถึงobjสองครั้ง ฉันเดาการสร้างฟังก์ชั่นตัวช่วยไม่สามารถหลีกเลี่ยงได้? บางอย่างเช่นค่า (obj)
Steven Haryanto

วิธีการใด ๆ เหล่านี้สามารถใช้เป็นชิม ตัวอย่างเช่น:Object.values = obj => Object.keys(obj).map(key => obj[key]);
qubyte

1
โซลูชัน ECMA 5 ควรทำงานในเบราว์เซอร์สมัยใหม่ทั้งหมด ECMA 6 ยังไม่ได้รับการสรุปและการสนับสนุนเบื้องต้นในเบราว์เซอร์ทั้งหมด ใน Chrome มีการใช้งาน ECMA 6 บางส่วน แต่ถูกปิดใช้งาน ใน Firefox การสนับสนุนดีกว่า แต่ความเข้าใจของอาเรย์นั้นผิด (ดังที่ได้กล่าวไว้) ฉันคิดว่าการใช้กาลอนาคตของฉันจะบอกเป็นนัย @JacekLampart โซลูชันใดที่ทำให้คุณมีข้อผิดพลาด
qubyte

2
ฉันไม่สามารถจินตนาการได้ว่าทำไมเราต้องรอให้ ES2017 ได้รับเมธอด Object.values ​​()
Herbertusz

31

นี่คือฟังก์ชั่นที่นำกลับมาใช้ใหม่เพื่อรับค่าลงในอาร์เรย์ มันต้องคำนึงถึงต้นแบบด้วย

Object.values = function (obj) {
    var vals = [];
    for( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            vals.push(obj[key]);
        }
    }
    return vals;
}

15
การแก้ไขObjectไม่ได้เป็นปัญหามากนัก ( Object.keysเป็นเรื่องธรรมดาทั่วไป) คุณอาจกำลังคิดที่จะดัดแปลงต้นแบบของวัตถุ
sandstrom

ทำไมคุณจะต้องไปทดสอบด้วยhasOwnProperty()? กุญแจจะวนซ้ำภายในวงของวัตถุนั้นไม่ได้รับทรัพย์สินได้อย่างไร
1252748

4
Google it @thomas มันสำคัญนะ มันอาจมีคุณสมบัติจากโซ่ต้นแบบ
Joe

28

หากคุณมีสิทธิ์เข้าถึง Underscore.js คุณสามารถใช้_.valuesฟังก์ชันดังนี้:

_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]

@MathieuAmiot - สนใจอธิบายไหม?
Paden

lodash เป็นการทดแทนที่เข้ากันได้กับ api สำหรับขีดล่าง, a (way) ที่เร็วกว่า
Mathieu Amiot

@Paden นี่เป็นคำถามที่เกี่ยวข้องกับ SO: stackoverflow.com/questions/13789618/…
jichi

2
lodash ไม่จำเป็นสำหรับสิ่งนี้และจะขยายฐานรหัสของคุณ
dman

14

หากคุณต้องการอาร์เรย์ของค่าจริงๆฉันพบว่าเครื่องนี้สะอาดกว่าการสร้างอาร์เรย์ที่มีห่วงสำหรับ ... ใน

ECMA 5.1+

function values(o) { return Object.keys(o).map(function(k){return o[k]}) }

เป็นที่น่าสังเกตว่าในกรณีส่วนใหญ่คุณไม่จำเป็นต้องมีค่ามากมายมันจะเร็วกว่าในการทำสิ่งนี้:

for(var k in o) something(o[k]);

สิ่งนี้ทำซ้ำผ่านคีย์ของ Object o ในแต่ละการวนซ้ำ k ถูกตั้งค่าเป็นคีย์ของ o


9

ES5 Object.keys

var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]

3
ทำไมสิ่งนี้จึงถูกลดระดับลง ฉันจะบอกว่านี่เป็นหนึ่งในโซลูชั่นที่สะอาดที่สุด
เซบาสเตียนโฮจาส

ฉันไม่รู้ทำไมลงคะแนนนี้ นี่เป็นวิธีที่ง่ายและบริสุทธิ์ที่สุดใน js โดยไม่ต้องใช้ไลบรารีหรือยูทิลิตี้อื่น ๆ
sanjeev

5

คุณสามารถวนลูปผ่านปุ่มต่างๆได้:

foo = {one:1, two:2, three:3};
for (key in foo){
    console.log("foo["+ key +"]="+ foo[key]);
}

จะส่งออก:

foo[one]=1
foo[two]=2
foo[three]=3

2
คุณต้องตรวจสอบ `hasOwnProperty () 'หากคุณต้องการหลีกเลี่ยงแอททริบิวต์ที่สืบทอดมา
0xc0de

3

สำหรับผู้ที่ปรับตัวคนแรก ๆ ในยุค CofeeScript นี่เป็นอีกสิ่งที่เทียบเท่ากับมัน

val for key,val of objects

ซึ่งอาจดีกว่านี้เพราะobjectsสามารถลดให้พิมพ์อีกครั้งและลดความสามารถในการอ่าน

objects[key] for key of objects

3

ใช้ polyfill เช่น:

if(!Object.values){Object.values=obj=>Object.keys(obj).map(key=>obj[key])}

จากนั้นใช้

Object.values(my_object)

3) กำไร!


3

ECMA2017 เป็นต้นไป:

Object.values(obj) จะดึงค่าคุณสมบัติทั้งหมดเป็นอาร์เรย์

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values


ควรทราบว่าสิ่งนี้จะไม่ส่งคืนคุณสมบัติที่สืบทอดมา
รวย remer

การทำงานที่ดี .... บรรทัดเดียวบันทึกวันของฉัน ....
กอง Kiddy

2

เห็นได้ชัดว่าตามที่ฉันเพิ่งเรียนรู้นี่เป็นวิธีที่เร็วที่สุดที่จะทำ:

var objs = {...};
var objKeys = Object.keys(obj);
for (var i = 0, objLen = objKeys.length; i < objLen; i++) {
    // do whatever in here
    var obj = objs[objKeys[i]];
}

คุณสามารถใส่โค้ดตัวอย่างหรือ jsfiddle ของตัวอย่างนี้ได้หรือไม่? ขอบคุณ
Chris22

2

คำถามไม่ได้ระบุว่าต้องการคุณสมบัติที่สืบทอดและไม่สามารถนับได้เช่นกัน

มีคำถามเกี่ยวกับการรับทุกสิ่งคุณสมบัติที่สืบทอดและคุณสมบัติที่ไม่นับรวมที่ Google ไม่สามารถหาได้ง่าย

ทางออกของฉันคือ:

function getAllPropertyNames(obj) {
    let result = new Set();
    while (obj) {
        Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
        obj = Object.getPrototypeOf(obj);
    }
    return [...result];
}

จากนั้นวนซ้ำพวกเขาเพียงแค่ใช้ for-of loop


1

ใช้: Object.values()เราส่งผ่านวัตถุเป็นอาร์กิวเมนต์และรับค่าอาร์เรย์เป็นค่าส่งคืน

สิ่งนี้จะส่งคืนอาร์เรย์ของค่าคุณสมบัติที่นับได้ของวัตถุที่กำหนด คุณจะได้รับค่าเดียวกันโดยใช้การfor inวนซ้ำ แต่ไม่มีคุณสมบัติในต้นแบบ ตัวอย่างนี้อาจทำให้สิ่งต่าง ๆ ชัดเจนขึ้น:

function person (name) {
  this.name = name;
}

person.prototype.age = 5;

let dude = new person('dude');

for(let prop in dude) {
  console.log(dude[prop]);     // for in still shows age because this is on the prototype
}                              // we can use hasOwnProperty but this is not very elegant

// ES6 + 
console.log(Object.values(dude));
// very concise and we don't show props on prototype


1
const object1 = {
  a: 'somestring',
  b: 42
};

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// expected output:
// "a: somestring"
// "b: 42"
// order is not guaranteed

0

นี่คือฟังก์ชั่นที่คล้ายกับ array_values ​​ของ PHP ()

function array_values(input) {
  var output = [], key = '';
  for ( key in input ) { output[output.length] = input[key]; }
  return output;
}

ต่อไปนี้เป็นวิธีรับค่าของวัตถุหากคุณใช้ ES6 หรือสูงกว่า:

Array.from(values(obj));

ด้วยเหตุผลบางอย่างค่า () ทำงานใน Chrome และ Firefox แต่ไม่ได้อยู่ใน iojs / node
jaggedsoft

0

เข้ากันได้กับ ES7 แม้เบราว์เซอร์บางตัวยังไม่รองรับ

ตั้งแต่Object.values(<object>)จะถูกสร้างขึ้นในES7 &

ก่อนที่จะรอให้เบราว์เซอร์ทั้งหมดให้การสนับสนุนคุณสามารถปิดภายในเบราว์เซอร์:

Object.vals=(o)=>(Object.values)?Object.values(o):Object.keys(o).map((k)=>o[k])

จากนั้น:

Object.vals({lastname:'T',firstname:'A'})
 // ['T','A']

เมื่อเบราว์เซอร์เข้ากันได้กับ ES7 คุณจะไม่ต้องเปลี่ยนแปลงอะไรในรหัสของคุณ


0

ฉันรู้ฉันสายเล็ก ๆ น้อย ๆ แต่ที่นี่เป็นShimใหม่ Firefox 47 Object.valuesวิธี

Object.prototype.values = Object.prototype.values || function(obj) {
  return this.keys(obj).map(function(key){
    return obj[key];
  });
};


0

const myObj = { a:1, b:2, c:3 }

รับค่าทั้งหมด:

  • วิธีที่สั้นที่สุด:

    • const myValues = Object.values(myObj)
  • const myValues = Object.keys(myObj).map(key => myObj[key])



-5

ในการใช้ECMAScript5

 keys = Object.keys(object);

มิฉะนั้นถ้าเบราว์เซอร์ของคุณไม่รองรับให้ใช้ที่รู้จักกันดี for..in loop

for (key in object) {
    // your code here
}

17
คำถามกำลังถามค่าไม่ใช่กุญแจ
zachelrath

@zachelrath คุณพูดถูก - แต่สคริปต์นี้มีประโยชน์หากคุณต้องการรับค่าเพราะเมื่อคุณรู้รหัสคุณสามารถใช้object[key]เพื่อรับค่าในลูป
fridojet

2
@fridojet แต่สามารถทำได้ด้วยfor..in(และ hasOwnProperty) ดังนั้นมันจึงไม่ได้รับอะไรเลย .. ฉันหวังว่า ECMAScript 5th จะเป็นตัวกำหนดObject.pairs(และObject.itemsสำหรับ[[key, value], ..]) แต่อนิจจามันไม่ได้
user2246674

-8

ตอนนี้ผมใช้Dojo ToolkitObject.valuesเนื่องจากเบราว์เซอร์รุ่นเก่าไม่สนับสนุน

require(['dojox/lang/functional/object'], function(Object) {
    var obj = { key1: '1', key2: '2', key3: '3' };
    var values = Object.values(obj);
    console.log(values);
});

ผลผลิต:

['1', '2', '3']

5
อาร์เรย์พูดไม่ถูกต้อง คุณมีอาร์เรย์ของสตริงแทนอาร์เรย์ของตัวเลข
qubyte

-10

ใช้

console.log(variable)

และถ้าคุณใช้ google chrome เปิดคอนโซลโดยใช้ Ctrl + Shift + j

ไปที่ >> คอนโซล

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