Câu hỏi Làm thế nào để lặp qua một đối tượng JavaScript đơn giản với các đối tượng như các thành viên?


Làm thế nào tôi có thể lặp qua tất cả các thành viên trong một đối tượng JavaScript bao gồm các giá trị là các đối tượng.

Ví dụ, làm thế nào tôi có thể lặp qua điều này (truy cập vào "your_name" và "your_message" cho mỗi)?

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}

1247
2018-05-28 16:18


gốc


có thể trùng lặp Lặp qua đối tượng JavaScript - BuZZ-dEE


Các câu trả lời:


for (var key in validation_messages) {
    // skip loop if the property is from prototype
    if (!validation_messages.hasOwnProperty(key)) continue;

    var obj = validation_messages[key];
    for (var prop in obj) {
        // skip loop if the property is from prototype
        if(!obj.hasOwnProperty(prop)) continue;

        // your code
        alert(prop + " = " + obj[prop]);
    }
}

1802
2018-05-28 16:20



Internet Explorer không đồng ý (thở dài), nói "Object không hỗ trợ thuộc tính hoặc phương thức này" khi bạn làm obj [prop]. Tôi vẫn chưa tìm được giải pháp cho việc này. - user999717
Nếu bạn đang sử dụng jQuery, $ .each () / does / work trong IE. - user999717
@ MildFuzz thực sự nó có ý nghĩa nếu bạn xem xét rằng các đối tượng JS không cần thiết có các phím số. Bạn không thể chỉ lặp qua một đối tượng. JS's for in rất giống với truyền thống foreach. - Jake Wilson
cho ... trong là một giải pháp tốt, nhưng nếu bạn sử dụng lời hứa trong vòng lặp for () - cẩn thận, bởi vì nếu bạn tạo một var trong vòng lặp, bạn không thể sử dụng nó trong lời hứa 'then-function'. Bạn var trong vòng lặp tồn tại chỉ có một thời gian, do đó, nó có trong mọi chức năng sau đó giống nhau, ngay cả giá trị cuối cùng. Nếu bạn gặp sự cố đó, hãy thử "Object.keys (obj) .forEach" hoặc câu trả lời của tôi bên dưới. - Biber


Theo ECMAScript 5, bạn có thể kết hợp Object.keys() và Array.prototype.forEach():

var obj = {
  first: "John",
  last: "Doe"
};

//
//	Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

  console.log(key, obj[key]);

});


569
2018-04-20 22:04



1 cho ngắn gọn của mã nhưng rõ ràng, không thực hiện hiệu quả như một cho đáng ngạc nhiên. JSPerf - cho so với Object.keys - techiev2
Cẩn thận với lỗi này bằng cách sử dụng phương pháp này: "TypeError: Object.keys được gọi là không đối tượng". Các for ... in ... hasOwnProperty mô hình có thể được gọi trên bất cứ điều gì, như xa như tôi có thể nói (đối tượng, mảng, null, không xác định, đúng, sai, số nguyên thủy, các đối tượng). - theazureshadow
Lưu ý rằng IE7 không hỗ trợ điều này. - Paul D. Waite
@ techiev2 những bài kiểm tra đó không bao giờ hợp lệ. Xem các cập nhật của tôi cho trạng thái hiệu suất hiện tại: jsperf.com/objdir/20 - OrganicPanda
@ techiev2: không phải Object.keys() mà làm cho nó chậm, nó thay vì forEach() và truy cập lặp lại vào .length! Nếu bạn sử dụng cổ điển forthay vào đó, nó nhanh gấp hai lần for..in + hasOwnProperty() trong Firefox 33. - CoDEmanX


Vấn đề với điều này

for (var key in validation_messages) {
   var obj = validation_messages[key];
   for (var prop in obj) {
      alert(prop + " = " + obj[prop]);
   }
}

là bạn cũng sẽ lặp qua nguyên mẫu của đối tượng nguyên thủy.

Với cái này bạn sẽ tránh nó:

for (var key in validation_messages) {
   if (validation_messages.hasOwnProperty(key)) {
      var obj = validation_messages[key];
      for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
            alert(prop + " = " + obj[prop]);
         }
      }
   }
}

364
2018-05-19 20:58



Tóm lại: kiểm tra hasOwnProperty bên trong của bạn for- -in vòng lặp. - Rory O'Kane
Lưu ý rằng điều này chỉ cần thiết nếu đối tượng của bạn có các phương thức nguyên mẫu HAS. Ví dụ, nếu đối tượng bạn đang lặp qua chỉ là một đối tượng JSON, bạn sẽ không cần kiểm tra này. - rednaw
@rednaw Để được an toàn, tôi sử dụng kiểm tra đó vì Object.prototype có thể được sửa đổi. Không có kịch bản sane nào làm được điều đó, nhưng bạn không thể kiểm soát những đoạn mã nào có thể được chạy trong trang của bạn bằng các phần mở rộng trình duyệt điên rồ. Tiện ích trình duyệt chạy trong trang của bạn (trên hầu hết các trình duyệt) và chúng có thể gây ra các sự cố lạ (ví dụ: đặt window.setTimeout thành null!). - robocat


Trong ES6 bạn có thể lặp qua một đối tượng như thế này: (sử dụng chức năng mũi tên)

Object.keys(myObj).forEach(key => {
    console.log(key);          // the name of the current key.
    console.log(myObj[key]);   // the value of the current key.
});

jsbin

Trong ES7 bạn có thể dùng Object.entries thay vì Object.keys và lặp qua một đối tượng như thế này:

Object.entries(myObj).forEach(([key, val]) => {
    console.log(key);          // the name of the current key.
    console.log(val);          // the value of the current key.
});

Ở trên cũng sẽ hoạt động như một lót:

Object.keys(myObj).forEach(key => console.log(key, myObj[key]));

jsbin

Trong trường hợp bạn muốn lặp qua các đối tượng lồng nhau, bạn có thể sử dụng đệ quy Hàm (ES6):

const loopNestedObj = (obj) => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === 'object') loopNestedObj(obj[key]);  // recurse.
    else console.log(key, obj[key]);  // or do something with key and val.
  });
};

jsbin

Giống như hàm trên, nhưng với ES7 Object.entries thay vì Object.keys:

const loopNestedObj = (obj) => {
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === 'object') loopNestedObj(val);  // recurse.
    else console.log(key, val);  // or do something with key and val.
  });
};

Nếu bạn vào lập trình chức năng bạn có thể dùng Object.keys/Object.entries để liệt kê đối tượng, sau đó xử lý các giá trị và sau đó sử dụng reduce() để chuyển đổi trở lại đối tượng mới.

const loopNestedObj = (obj) => 
  Object.keys(obj)
    // Use .filter(), .map(), etc. if you need.
    .reduce((newObj, key) => 
      (obj[key] && typeof obj[key] === 'object') ?
        {...newObj, [key]: loopNestedObj(obj[key])} :  // recurse.
        {...newObj, [key]: obj[key]},                  // Define value.
      {});

145
2018-01-09 14:22



cho ES7 của bạn bằng cách sử dụng ví dụ Object.entries, bạn cần phải bọc các tham số hàm mũi tên [key, val] trong dấu ngoặc đơn như: `Object.entries (myObj) .forEach (([key, val]) => {/ * statements * /} - Puiu
Tôi nghĩ sẽ hữu ích khi thêm vào một thực tế là Object.entries và Object.keys không lặp lại trên nguyên mẫu, đó là sự khác biệt lớn giữa nó và cấu trúc trong cấu trúc. - steviejay


Sử dụng Underscore.js’s _.each:

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});

93
2017-09-16 12:11



Cảm ơn Tim, sử dụng dấu gạch dưới để chắc chắn là tốt để có một lựa chọn nhanh chóng và sạch sẽ. - The Coder


Nếu bạn sử dụng đệ quy, bạn có thể trả về các thuộc tính đối tượng của bất kỳ độ sâu nào

function lookdeep(object){
    var collection= [], index= 0, next, item;
    for(item in object){
        if(object.hasOwnProperty(item)){
            next= object[item];
            if(typeof next== 'object' && next!= null){
                collection[index++]= item +
                ':{ '+ lookdeep(next).join(', ')+'}';
            }
            else collection[index++]= [item+':'+String(next)];
        }
    }
    return collection;
}

//example

var O={
    a:1, b:2, c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';


/*  returned value: (String)
O={
    a:1, 
    b:2, 
    c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
}

*/

52
2018-05-28 18:03



Cẩn thận với các vòng lặp, như gọi điều này trên một nút DOM. - theazureshadow


Tôi biết đã muộn rồi, nhưng tôi phải mất 2 phút để viết câu trả lời tối ưu và được cải tiến này của câu trả lời của AgileJon:

var key, obj, prop, owns = Object.prototype.hasOwnProperty;

for (key in validation_messages ) {

    if (owns.call(validation_messages, key)) {

        obj = validation_messages[key];

        for (prop in obj ) {

            // using obj.hasOwnProperty might cause you headache if there is
            // obj.hasOwnProperty = function(){return false;}
            // but owns will always work 
            if (owns.call(obj, prop)) {
                console.log(prop, "=", obj[prop]);
            }

        }

    }

}

29
2017-09-05 06:17



Tại sao bạn lưu trữ hasOwnProperty trong owns và sau đó gọi owns.call(obj, prop) thay vì chỉ gọi obj.hasOwnProperty(prop) như câu trả lời này làm? - Rory O'Kane
Bởi vì obj có thể có hasOwnProperty chức năng được xác định trên nó tự vì vậy nó sẽ không sử dụng một từ Object.prototype. Bạn có thể thử trước for vòng lặp như thế này obj.hasOwnProperty = function(){return false;} và nó sẽ không lặp qua bất kỳ tài sản nào. - Azder
@Azder +1 cho câu trả lời và +1 nếu tôi có thể cho những điều tốt đẹp về Object.prototype.hasOwnProperty. Tôi thấy rằng trước đó bên trong mã nguồn của thư viện gạch dưới nhưng không biết tại sao. - Samuel


for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}

27
2018-05-28 16:20





Câu trả lời này là tổng hợp các giải pháp được cung cấp trong   đăng với một số hiệu suất   phản hồi. Tôi nghĩ có 2   các trường hợp sử dụng và OP không đề cập đến nếu anh ta cần truy cập các khóa để sử dụng chúng   trong quá trình lặp.

I. các khóa cần được truy cập,

 các of và Object.keys tiếp cận

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

 các in tiếp cận

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

Sử dụng cái này một cách thận trọng, vì nó có thể in các đặc tính nguyên mẫu của obj

 phương pháp ES7

for (const [key, value] of Object.entries(obj)) {

}

Tuy nhiên, tại thời điểm chỉnh sửa, tôi sẽ không đề xuất phương pháp ES7, vì JavaScript khởi tạo rất nhiều biến trong nội bộ để xây dựng quy trình này (xem phản hồi về bằng chứng). Trừ khi bạn không phát triển một ứng dụng khổng lồ xứng đáng được tối ưu hóa, thì nó là ok nhưng nếu tối ưu hóa là ưu tiên của bạn, bạn nên suy nghĩ về nó.

II. chúng tôi chỉ cần truy cập vào từng giá trị,

 các of và Object.values tiếp cận

let v;
for (v of Object.values(obj)) {

}

Thêm phản hồi về các bài kiểm tra:

  • Caching Object.keys hoặc là Object.values hiệu suất là không đáng kể

Ví dụ,

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • Dành cho Object.values case, sử dụng native for vòng lặp với các biến được lưu trong bộ nhớ cache trong Firefox có vẻ nhanh hơn một chút so với việc sử dụng for...of vòng lặp. Tuy nhiên sự khác biệt không quan trọng và Chrome đang chạy for...of nhanh hơn so với bản địa for vòng lặp, vì vậy tôi khuyên bạn nên sử dụng for...of khi giải quyết Object.values trong mọi trường hợp (thử nghiệm thứ 4 và thứ 6).

  • Trong Firefox, for...in vòng lặp thực sự chậm, vì vậy khi chúng tôi muốn lưu vào bộ nhớ cache khóa trong khi lặp lại, tốt hơn nên sử dụng Object.keys. Cộng với Chrome đang chạy cả hai cấu trúc ở tốc độ bằng nhau (thử nghiệm đầu tiên và cuối cùng).

Bạn có thể kiểm tra các bài kiểm tra ở đây:    https://jsperf.com/es7-and-misc-loops


16
2017-09-24 03:34



Ví dụ ES7 hoạt động như một sự quyến rũ với React Native! - Ty Bailey
Câu trả lời rực rỡ !! - CandleCoder


for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}

8
2018-05-28 16:21