Câu hỏi Làm cách nào để lặp lại hoặc liệt kê một đối tượng JavaScript?


Tôi có một đối tượng JavaScript như sau:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Bây giờ tôi muốn lặp qua tất cả p yếu tố (p1,p2,p3...) và nhận được chìa khóa và giá trị của họ. Làm thế nào tôi có thể làm điều đó?

Tôi có thể sửa đổi đối tượng JavaScript nếu cần. Mục tiêu cuối cùng của tôi là lặp qua một số cặp khóa giá trị và nếu có thể, tôi muốn tránh sử dụng eval.


2133
2018-03-26 06:01


gốc


Tôi đã thay đổi JSON thành JavaScript (đối tượng) để tránh nhầm lẫn giữa các đối tượng literals và JSON. - Felix Kling
Trong khi lặp qua bộ sưu tập, bạn nên quan tâm đến việc tối ưu hóa. Vì nó có thể ảnh hưởng đến hiệu suất trang. - Zaheer Ahmed
Javascript in đẹp:  j11y.io/demos/prettyprint  Tôi là một fan hâm mộ lớn của hàm kết xuất  ajaxian.com/archives/javascript-variable-dump-in-coldfusion - Kiquenet
dump chức năng:  github.com/ozmartian/js-cfdump - Kiquenet


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


Bạn có thể dùng for-in vòng lặp như được hiển thị bởi những người khác. Tuy nhiên, bạn cũng phải đảm bảo rằng khóa bạn nhận được là một thuộc tính thực sự của một đối tượng và không xuất phát từ nguyên mẫu.

Đây là đoạn trích:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}


3467
2018-03-26 06:12



Đề xuất rằng bạn thay đổi đường cảnh báo chỉ để rõ ràng alert(key + " -> " + JSON.stringify(p[key])); - Steve Midgley
Bạn có thể giải thích sự cần thiết của hasOwnProperty? Những gì bạn có nghĩa là bởi nguyên mẫu? - kamaci
Trong javascript, mọi đối tượng đều có một cặp cặp khóa-giá trị tích hợp có siêu thông tin. Khi bạn lặp qua tất cả các cặp khóa-giá trị cho một đối tượng bạn cũng đang lặp qua chúng. hasOwnPropery () lọc chúng ra. - danieltalsky
Thực ra, Tại không được chấp nhận. Đối với mỗi ... trong Là. Nhưng tôi thực sự thích thuật ngữ nhà khảo cổ học... Tôi sẽ phải bắt đầu sử dụng nó. - Ben Y
mỗi đối tượng trong javascript (thực ra là cặp khóa-giá trị) có một thuộc tính được gọi là __proto__ hoặc là prototype. Thuộc tính này có tham chiếu đến đối tượng cha của nó. Một đối tượng sẽ tự động kế thừa thuộc tính từ cha mẹ của nó. Đây là lý do sử dụng hasOwnProperty, có nghĩa là chúng tôi quan tâm đến các đối tượng sở hữu tài sản và không quan tâm đến các đối tượng sở hữu của nó. - Zubair Alam


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

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

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ES6 bổ sung for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ES2017 thêm Object.entries() mà tránh phải tra cứu từng giá trị trong đối tượng gốc:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

Cả hai Object.keys() và Object.entries() lặp lại các thuộc tính theo thứ tự giống như một for...in vòng lặp nhưng bỏ qua chuỗi nguyên mẫu. Chỉ các thuộc tính đếm được của riêng đối tượng được lặp lại.

Chỉnh sửa: ES2016 → ES6


627
2018-04-20 21:59



Tại sao tiêu chuẩn không cung cấp Object.forEach(obj, function (value, key) {...})? :( Chắc chắn obj.forEach(function...) sẽ ngắn hơn và bổ sung Array.prototype.forEach, nhưng điều đó sẽ có nguy cơ có đối tượng xác định forEach bất động sản. tôi giả sử Object.keys bảo vệ chống lại việc gọi lại sửa đổi các phím của đối tượng. - David Harkness
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); } - David Harkness
@DavidHarkness Có Object.entries trong ES2017. Ở đó bạn có thể làm như sau: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value)) ([key, value] là mảng destructuring, để truy cập trực tiếp cả hai mục. Và bạn phải bọc các tham số trong các parens bổ sung.) - Andreas Linnert
làm sao tôi có thể lấy index của khóa trong json? Hoặc nếu yêu cầu tôi nên sử dụng một truy cập riêng biệt? - Saravanabalagi Ramachandran
for...of là tiêu chuẩn ES6, không phải ES2016. - Rax Weber


Bạn phải sử dụng vòng lặp for-in

Nhưng hãy cẩn thận khi sử dụng loại vòng lặp này, vì điều này sẽ lặp lại tất cả các thuộc tính dọc theo chuỗi nguyên mẫu.

Do đó, khi sử dụng các vòng lặp for-in, hãy luôn sử dụng hasOwnProperty để xác định xem thuộc tính hiện tại trong lần lặp lại có thực sự là thuộc tính của đối tượng mà bạn đang kiểm tra hay không:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

300
2018-03-26 06:12



Điều này tốt hơn so với giải pháp của levik bởi vì nó cho phép logic chính chỉ là một vòng lặp lồng nhau thay vì hai; làm cho việc đọc mã dễ dàng hơn. Mặc dù tôi đã mất các dấu ngoặc xung quanh tiếp tục; họ là thừa. - SystemicPlural
Tôi sẽ không xóa { } cá nhân vì một if mà không có họ làm cho nó một chút không rõ ràng những gì là một phần của if và cái gì không. Nhưng tôi đoán đó chỉ là vấn đề quan điểm :) - pimvdb
Có, tôi thích giữ { } chủ yếu để tránh nhầm lẫn nếu sau này cần phải thêm thứ gì đó vào if phạm vi. - Andreas Grech
Đọc nhận xét trước của tôi, tôi nhận ra rằng tôi đã không sử dụng các thuật ngữ chính xác, bởi vì tôi đã nói "nếu phạm vi"; nhưng hãy nhớ rằng JavaScript chỉ có phạm vi chức năng. Vì vậy, những gì tôi thực sự có nghĩa là "nếu khối". - Andreas Grech
eomeroff, nếu bạn thực sự lo lắng về điều đó, bạn luôn có thể làm điều gì đó như: Object.prototype.hasOwnProperty.call(p, prop)  Tuy nhiên, điều này cũng không thể bảo vệ chống lại các thao tác đối với Object.prototype ... - jordancpaul


Câu hỏi sẽ không hoàn thành nếu chúng ta không đề cập đến các phương pháp thay thế để lặp qua các đối tượng.

Ngày nay nhiều thư viện JavaScript nổi tiếng cung cấp các phương pháp riêng của họ để lặp qua các bộ sưu tập, tức là hơn mảng, các đối tượngcác đối tượng giống mảng. Các phương pháp này thuận tiện để sử dụng và hoàn toàn tương thích với mọi trình duyệt.

  1. Nếu bạn làm việc với jQuery, bạn có thể sử dụng jQuery.each() phương pháp. Nó có thể được sử dụng để liên tục lặp qua cả hai đối tượng và mảng:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  2. Trong Underscore.js bạn có thể tìm thấy phương pháp _.each(), lặp lại trên một danh sách các phần tử, mỗi lần cho phép một hàm được cung cấp (chú ý đến thứ tự của các đối số trong lặp lại chức năng!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  3. Lo-Dash cung cấp một số phương thức để lặp qua các thuộc tính đối tượng. Căn bản _.forEach() (hoặc bí danh của nó _.each()) hữu ích cho việc lặp qua cả hai đối tượng và mảng, tuy nhiên các đối tượng (!) với length tài sản được xử lý như mảng, và để tránh hành vi này, nó được đề nghị sử dụng _.forIn() và _.forOwn() phương pháp (những thứ này cũng có value đối số đến trước):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    

    _.forIn() lặp lại sở hữu và kế thừa liệt kê các thuộc tính của một đối tượng, trong khi _.forOwn() chỉ lặp lại sở hữu các thuộc tính của một đối tượng (về cơ bản là kiểm tra hasOwnProperty chức năng). Đối với các đối tượng đơn giản và các đối tượng literals, bất kỳ phương thức nào trong số này cũng sẽ hoạt động tốt.

Nói chung tất cả các phương pháp mô tả có cùng một hành vi với bất kỳ đối tượng được cung cấp. Bên cạnh việc sử dụng nguồn gốc for..in vòng lặp thường sẽ là nhanh hơn hơn bất kỳ trừu tượng nào, chẳng hạn như jQuery.each(), các phương pháp này dễ sử dụng hơn, yêu cầu ít mã hóa hơn và cung cấp xử lý lỗi tốt hơn.


231
2018-01-20 17:58



Để có được giá trị: $ .each (obj, function (key, value) {console.log (value.title);}); - Ravi Ram
Chỉ cần vui như thế nào gạch dưới và jquery thay đổi các thông số :) - ppasler


Trong ECMAScript 5 bạn có cách tiếp cận mới trong các trường lặp của chữ - Object.keys

Bạn có thể xem thêm thông tin MDN

Lựa chọn của tôi dưới đây là giải pháp nhanh hơn trong các phiên bản trình duyệt hiện tại (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Bạn có thể so sánh hiệu suất của phương pháp này với các triển khai khác nhau trên jsperf.com:

Hỗ trợ trình duyệt bạn có thể thấy trên Bảng tương thích của Kangax

Đối với trình duyệt cũ bạn có đơn giản và đầy polyfill

UPD:

so sánh hiệu suất cho tất cả các trường hợp phổ biến nhất trong câu hỏi này perfjs.info:

lặp lại đối tượng theo nghĩa đen


47
2017-11-16 19:59



Thật vậy, tôi chỉ muốn đăng phương pháp này. Nhưng bạn đánh tôi với nó :( - Jamie Hutber
jsperf.com/object-iteration-comparison - Jason


Bạn chỉ có thể lặp qua nó như:

for (var key in p) {
  alert(p[key]);
}

Lưu ý rằng key sẽ không đưa vào giá trị của tài sản, nó chỉ là một giá trị chỉ mục.


30
2018-03-26 06:05



Điều này được lặp đi lặp lại và thậm chí không hoàn toàn chính xác. Bạn cần phải có một kiểm tra hasOwnProperty để làm cho công việc này đúng cách - Vatsal


Vì es2015 ngày càng trở nên phổ biến hơn, tôi đăng câu trả lời này bao gồm việc sử dụng trình tạo và trình lặp để thuận tiện lặp qua [key, value] cặp. Như nó có thể có trong các ngôn ngữ khác ví dụ như Ruby.

Ok đây là một mã:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Tất cả thông tin về làm thế nào bạn có thể làm một iterator và máy phát điện bạn có thể tìm thấy tại trang phát triển Mozilla.

Hy vọng Nó đã giúp một ai đó.

CHỈNH SỬA:

ES2017 sẽ bao gồm Object.entries sẽ lặp lại [key, value] cặp trong các đối tượng dễ dàng hơn nhiều. Nó bây giờ được biết rằng nó sẽ là một phần của một tiêu chuẩn theo ts39 thông tin sân khấu.

Tôi nghĩ rằng đó là thời gian để cập nhật câu trả lời của tôi để cho nó trở nên tươi mới hơn bây giờ.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Bạn có thể tìm thêm thông tin về mức sử dụng MDN trang


24
2017-08-27 09:06



cảm ơn bạn! bây giờ các đồng nghiệp của tôi sẽ không chế nhạo tôi cho JS phong cách năm 2005 của tôi! - the0ther
Điều này trông hoàn toàn không cần thiết / không cần thiết với tôi. Bạn có thêm nó vào mọi đối tượng trong hệ thống của bạn không? Tôi nghĩ rằng điểm cung cấp một iterator là để bạn có thể làm `cho (const [k, v] của myObject) '. Nó trông giống như mã phụ cung cấp ít giá trị bổ sung. - Dean Radcliffe