Làm thế nào để lặp lại một đối tượng JavaScript?


422

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

{
    abc: '...',
    bca: '...',
    zzz: '...',
    xxx: '...',
    ccc: '...',
    // ...
}

Tôi muốn sử dụng một forvòng lặp để có được các thuộc tính của nó. Và tôi muốn lặp lại nó trong các phần (không phải tất cả các thuộc tính đối tượng cùng một lúc).

Với một mảng đơn giản tôi có thể làm điều đó với một forvòng lặp tiêu chuẩn :

for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last

Nhưng làm thế nào để làm điều đó với các đối tượng?


22
Hãy nhớ rằng các thuộc tính đối tượng không được lưu trữ theo thứ tự. Khi bạn lặp lại một đối tượng, không có gì đảm bảo cho thứ tự chúng sẽ xuất hiện.
James Allardice

Câu trả lời:


850

Đối với hầu hết các đối tượng, sử dụng for .. in:

for (let key in yourobject) {
  console.log(key, yourobject[key]);
}

Với ES6, nếu bạn cần cả khóa và giá trị cùng một lúc, hãy làm

for (let [key, value] of Object.entries(yourobject)) {
    console.log(key, value);
}

Để tránh đăng nhập các thuộc tính được kế thừa, hãy kiểm tra với hasOwnProperty :

for (let key in yourobject) {
   if (yourobject.hasOwnProperty(key)) {
      console.log(key, yourobject[key]);
   }
}

Bạn không cần kiểm tra hasOwnPropertykhi lặp lại trên các phím nếu bạn đang sử dụng một đối tượng đơn giản (ví dụ: đối tượng bạn tự tạo {}).

Tài liệu MDN này giải thích chung hơn về cách xử lý các đối tượng và thuộc tính của chúng.

Nếu bạn muốn làm điều đó "trong khối", tốt nhất là trích xuất các khóa trong một mảng. Vì đơn hàng không được đảm bảo, đây là cách thích hợp. Trong các trình duyệt hiện đại, bạn có thể sử dụng

let keys = Object.keys(yourobject);

Để tương thích hơn, bạn nên làm điều này:

 let keys = [];
 for (let key in yourobject) {      
     if (yourobject.hasOwnProperty(key)) keys.push(key);
 }

Sau đó, bạn có thể lặp lại các thuộc tính của mình theo chỉ mục yourobject[keys[i]]::

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}

3
OP muốn thực hiện điều này trong khối, không phải tất cả các khóa trong một vòng lặp.
pawel

Đúng. Không đầy đủ đối tượng trong một vòng lặp.
nkuhta

2
@Cerbrus OP all sẵn sàng biết cách lặp một mảng trong các phần. Sử dụng keystừ mã đã cho là đủ.
Yoshi

2
@Cerbrus Vui lòng đọc trước khi bình luận! Điều gì không rõ ràng trong "Để tương thích hơn, bạn nên làm điều này tốt hơn" ?
Denys Séguret

2
@ am05mhz Như tôi đã nói, nó vô dụng với hầu hết các đối tượng. Nhưng không phải cho tất cả. Hãy thử điều này: jsbin.com/hirivubuta/1/edit?js,console,output
Denys Séguret

61

Đây là một giải pháp lặp khác cho các trình duyệt hiện đại:

Object.keys(obj)
  .filter((k, i) => i >= 100 && i < 300)
  .forEach(k => console.log(obj[k]));

Hoặc không có chức năng lọc:

Object.keys(obj).forEach((k, i) => {
    if (i >= 100 && i < 300) {
        console.log(obj[k]);
    }
});

Tuy nhiên, bạn phải xem xét rằng các thuộc tính trong đối tượng JavaScript không được sắp xếp, tức là không có thứ tự.


Nếu tôi sẽ phá vỡ vòng lặp, nó sẽ bắt đầu từ đầu đối tượng vào lần tới, đó không phải là cách đúng đắn.
nkuhta

21

Sử dụng Object.entriesbạn làm một cái gì đó như thế này.

 // array like object with random key ordering
 const anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]

Phương thức Object.entries () trả về một mảng thuộc tính liệt kê riêng của đối tượng đã cho [khóa, giá trị]

Vì vậy, bạn có thể lặp lại qua Object và có keyvaluecho từng đối tượng và nhận được một cái gì đó như thế này.

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
   const key   = obj[0];
   const value = obj[1];

   // do whatever you want with those values.
});

hoặc như thế này

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

Để tham khảo, hãy xem tài liệu MDN cho mục nhập đối tượng


17

Với các tính năng ES6 / ES2015 mới, bạn không phải sử dụng một đối tượng nữa để lặp lại hàm băm. Bạn có thể sử dụng Bản đồ . Bản đồ Javascript giữ các khóa theo thứ tự chèn, nghĩa là bạn có thể lặp lại chúng mà không cần phải kiểm tra hasOwnProperty, thứ luôn thực sự là một hack.

Lặp lại trên bản đồ:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

hoặc sử dụng forEach:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

1
forEach là người được ưa thích
pungggi

14

Nếu bạn muốn khóa và giá trị khi lặp, bạn có thể sử dụng vòng lặp for cho ... với Object.entries .

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

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2

7

Cách đáng tin cậy duy nhất để làm điều này là lưu dữ liệu đối tượng của bạn vào 2 mảng, một trong các khóa và một cho dữ liệu:

var keys = [];
var data = [];
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        keys.push(key);
        data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
    }
}

Sau đó, bạn có thể lặp lại các mảng như bạn thường làm:

for(var i = 0; i < 100; i++){
    console.log(keys[i], data[i]);
    //or
    console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
    console.log(keys[i], data[i]);
}

Tôi không sử dụng Object.keys(obj), vì đó là IE 9+.


3

-> nếu chúng ta lặp lại một đối tượng JavaScript bằng cách sử dụng và tìm khóa của mảng các đối tượng

Object.keys(Array).forEach(key => {

 console.log('key',key)

})

1

Nếu bạn muốn lặp lại toàn bộ đối tượng cùng một lúc, bạn có thể sử dụng for invòng lặp:

for (var i in obj) {
  ...
}

Nhưng nếu bạn muốn chia đối tượng thành các phần trong thực tế thì bạn không thể. Không có gì đảm bảo rằng các thuộc tính trong đối tượng theo bất kỳ thứ tự cụ thể nào. Do đó, tôi có thể nghĩ ra hai giải pháp.

Đầu tiên là "loại bỏ" các thuộc tính đã đọc:

var i = 0;
for (var key in obj) {
    console.log(obj[key]);
    delete obj[key];
    if ( ++i > 300) break;
}

Một giải pháp khác tôi có thể nghĩ đến là sử dụng Array of Mảng thay vì đối tượng:

var obj = [['key1', 'value1'], ['key2', 'value2']];

Sau đó, forvòng lặp tiêu chuẩn sẽ hoạt động.


1

Cuối cùng tôi đã đưa ra một chức năng tiện ích tiện dụng với giao diện hợp nhất để lặp lại các Đối tượng, Chuỗi, Mảng, TypedArrays, Bản đồ, Bộ, (bất kỳ Iterables nào).

const iterate = require('@a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };

iterate(obj, (value, key) => console.log(key, value)); 
// a 1
// b 2
// c 3

https://github.com/alrik/iterate-javascript


1

Bạn có thể thử sử dụng lodash- Một thư viện tiện ích JavaScript hiện đại cung cấp mô đun, hiệu suất và tính năng bổ sung js cho đối tượng nhanh lặp lại: -

var  users  =   {
    'fred':     { 
        'user':   'fred',
            'age':  40 
    },
    'pebbles':  { 
        'user':   'pebbles',
         'age':  1 
    }
}; 
_.mapValues(users,  function(o)  { 
    return  o.age; 
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users,  'age')); // returns age property & value 
console.log(_.mapValues(users,  'user')); // returns user property & value 
console.log(_.mapValues(users)); // returns all objects 
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>


1

Đối với việc lặp lại đối tượng, chúng ta thường sử dụng một for..invòng lặp. Cấu trúc này sẽ lặp qua tất cả các thuộc tính có thể đếm được , bao gồm cả các thuộc tính được kế thừa thông qua thừa kế nguyên mẫu. Ví dụ:

let obj = {
  prop1: '1',
  prop2: '2'
}

for(let el in obj) {
  console.log(el);
  console.log(obj[el]);
}

Tuy nhiên, for..insẽ lặp qua tất cả các phần tử có thể đếm được và điều này sẽ không thể phân chia số lần lặp trong các phần. Để đạt được điều này, chúng ta có thể sử dụng hàm dựng sẵn Object.keys()để lấy tất cả các khóa của một đối tượng trong một mảng. Sau đó chúng ta có thể chia vòng lặp thành nhiều vòng lặp và truy cập các thuộc tính bằng cách sử dụng mảng phím. Ví dụ:

let obj = {
  prop1: '1',
  prop2: '2',
  prop3: '3',
  prop4: '4',
};

const keys = Object.keys(obj);
console.log(keys);


for (let i = 0; i < 2; i++) {
  console.log(obj[keys[i]]);
}


for (let i = 2; i < 4; i++) {
  console.log(obj[keys[i]]);
}


0
var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);

1
Thật ra là không. Điều này ngụ ý rằng Objects là theo thứ tự. Họ không phải. If you can make sense of the sentence it workedChỉ hoạt động vì chi tiết thực hiện. Nó không được đảm bảo để làm việc cả. Ngoài ra, bạn không nên TitleCase chức năng và biến của bạn. Đó là cho classes.
Florian Wendelborn

0

Thực sự là một PITA, đây không phải là một phần của Javascript tiêu chuẩn.

/**
 * Iterates the keys and values of an object.  Object.keys is used to extract the keys.
 * @param object The object to iterate
 * @param fn (value,key)=>{}
 */
function objectForEach(object, fn) {
    Object.keys(object).forEach(key => {
        fn(object[key],key, object)
    })
}

Lưu ý: Tôi đã chuyển các tham số gọi lại thành (giá trị, khóa) và thêm một đối tượng thứ ba để làm cho API phù hợp với các API khác.

Sử dụng nó như thế này

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});

1
nâng cấp chỉ cho tuyên bố của bạn trong câu đầu tiên. Mặc dù sẽ tốt hơn nếu giá trị là tham số đầu tiên, chỉ số hoặc tham số thứ hai chính và tham số thứ ba của đối tượng, để làm cho nó giống với mảng forEach () hơn. Tôi muốn giới thiệu lodash mặc dù.
HỢP ĐỒNG SAYS TÔI QUYỀN

Tôi thích ý tưởng về thứ tự (giá trị, khóa). Đó là cách một thư viện như Vue cũng làm điều đó. Bởi vì đối tượng là bối cảnh, mặc dù nó nghĩ rằng nó thuộc về tham số đầu tiên. Đó là tiêu chuẩn khá cho lập trình chức năng.
Steven Spungin

Tôi đồng ý ở đây, không phải vì ECMA-262 định nghĩa một mảng là một đối tượng có forEach (), map (), less (), filter (), mà tất cả đều gọi lại nhận lệnh [value, index, mảng] . Một đối tượng trong JS có thể được hiểu là chỉ là một bộ sưu tập khác; và sau đó các phương thức này trở nên thống nhất trong các tham số của chúng về [value, key | index, bối cảnh] (đây là điều mà lodash và undererscore đang làm). Theo tôi, giao thức "bộ sưu tập hợp nhất" này chỉ mạnh hơn. Ngoài ra, đối tượng không phải là bối cảnh: bạn có thể đặt thisthành bất cứ điều gì bạn thích cho cuộc gọi lại, vì cuộc gọi lại có bối cảnh riêng.
HỢP ĐỒNG SAYS TÔI QUYỀN

Có lẽ tôi nên sử dụng máy thu công việc thay vì này. Dù sao vẫn là một Pita; Tôi sẽ hoan nghênh các thông số theo thứ tự bất kỳ.
Steven Spungin

Ồ, tôi thấy rằng chúng ta có thể đã hiểu lầm nhau. Tôi đã luôn bình luận về các tham số gọi lại và thứ tự của chúng, không phải về objectForEachchức năng thực tế . Xin lỗi nếu điều đó gây nhầm lẫn.
HỢP ĐỒNG SAYS TÔI QUYỀN

0

Đúng. Bạn có thể lặp qua một đối tượng bằng vòng lặp for. Đây là một ví dụ

var myObj = {
    abc: 'ABC',
    bca: 'BCA',
    zzz: 'ZZZ',
    xxx: 'XXX',
    ccc: 'CCC',
}

var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
    console.log (k[i] + ": " + myObj[k[i]]);
}

LƯU Ý: ví dụ được đề cập ở trên sẽ chỉ hoạt động trong IE9 +. Xem hỗ trợ trình duyệt Objec.keys tại đây .


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.