Truy cập vào chỉ mục phần tử mảng ES6 bên trong vòng lặp for-of


227

Chúng ta có thể truy cập các phần tử mảng bằng cách sử dụng vòng lặp for:

for (const j of [1, 2, 3, 4, 5]) {
  console.log(j);
}

Làm thế nào tôi có thể sửa đổi mã này để truy cập vào chỉ mục hiện tại quá? Tôi muốn đạt được điều này bằng cách sử dụng cú pháp for-of, không forEach hay for-in.

Câu trả lời:


348

Sử dụng Array.prototype.keys:

for (const index of [1, 2, 3, 4, 5].keys()) {
  console.log(index);
}

Nếu bạn muốn truy cập cả khóa và giá trị, bạn có thể sử dụng Array.prototype.entries()với hàm hủy :

for (const [index, value] of [1, 2, 3, 4, 5].entries()) {
  console.log(index, value);
}


64
Trong trường hợp kỳ một người nào đó, tôi đã thử nghiệm for-ofvới .entries()và nó gấp đôi chậm so với .forEach(). jsperf.com/for-of-vs-foreach-with-index

1
@ K48 tốt đẹp để biết, sử dụng "đảo ngược cho-loop" nếu bạn muốn có nhanh nhất trong es: incredible-web.com/blog/...
nimo23

3
Thật không may, tôi cần phải nhường từ bên trong một vòng lặp lồng nhau. Không thể sử dụng forEach, vì hàm tạo ra các vấn đề phạm vi cho yieldtừ khóa. Nhưng tôi cần truy cập vào chỉ mục cho trường hợp sử dụng của mình, vì vậy ... ;;đó là vòng lặp cũ cơ bản , tôi đoán vậy.
Kyle Baker

2
@KyleBaker Và có gì sai với vòng lặp for .entires()?
Michał Perłakowski

1
Thay vào đó, vòng lặp ngược lại, bạn có thể lưu trữ bộ đệm dài jsperf.com/reverse-loop-vs-cache . For-of usefull để xử lý lặp lại khi bạn có thể xử lý luồng mà không tạo các mảng lớn trong RAM. Tốc độ vòng lặp sẽ không bị tắc nghẽn vì bạn sẽ có độ trễ I / O trong những trường hợp như vậy.
x'ES

289

Array#entries trả về chỉ mục và giá trị, nếu bạn cần cả hai:

for (let [index, value] of array.entries()) {

}

3
Với TypeScript: 'TS2495: Loại IterableIterator không phải là kiểu mảng hoặc kiểu chuỗi'. Có vẻ như điều này sẽ được giải quyết: github.com/Microsoft/TypeScript/pull/12346
Johannes

2
Ngoài ra Internet Explorer không được hỗ trợ.
Sammi

1
Không hay. Ném một lỗi, ví dụ như có document.styleSheets[0].cssRules.entries()hoặc thậm chí document.styleSheets.entries()và có thể nhiều cấu trúc lặp DOM khác. Vẫn phải sử dụng _.forEach()từlodash
Steven Pribilinskiy

2
@Steven: Nếu bạn không cần chỉ mục, bạn có thể làm for (var value of document.styleSheets) {}. Nếu bạn cần chỉ mục, trước tiên bạn có thể chuyển đổi giá trị thành một mảng thông qua Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling

1
Thật tuyệt! Array.fromlà FTW
Steven Pribilinskiy

28

Trong thế giới của các chức năng bản địa mới hào nhoáng này, đôi khi chúng ta quên mất những điều cơ bản.

for (let i = 0; i < arr.length; i++) {
    console.log('index:', i, 'element:', arr[i]);
}

Sạch sẽ, hiệu quả, và bạn vẫn có thể breakvòng lặp. Tặng kem! Bạn cũng có thể bắt đầu từ cuối và đi ngược với i--!

Lưu ý bổ sung: Nếu bạn đang sử dụng giá trị rất nhiều trong vòng lặp, bạn có thể muốn thực hiện const value = arr[i];ở đầu vòng lặp để tham khảo dễ đọc, dễ đọc.


1
Vâng. Tốt một, rõ ràng và đơn giản. Ồ, và như thế bạn có một cách siêu dễ dàng để truy cập khóa / chỉ mục của mảng.
Kết hợp

2
Bằng cách này, điều kiện sẽ trông như thế này -> for (let i = 0; i <Array.length; i ++) mà không có (-1) hoặc nó sẽ không lặp trong tất cả các phần tử của mảng.
Kết hợp

1
@Combine Bắt tốt! Tôi đã cập nhật câu trả lời của tôi để phản ánh lưu ý của bạn.
chris

4
Bạn vẫn có thể breaklà một for-offor (let [index, value] of array.entries())là xa dễ dàng hơn để đọc. Đi ngược lại dễ dàng như thêm .reverse().
Nigel B. Peck

2
Tôi nghĩ rằng đây là một câu trả lời hoàn toàn chấp nhận được cho câu hỏi này. Nó sẽ không bao giờ là câu trả lời được chấp nhận nhưng nó đã giúp vài chục người trở lên đã tìm kiếm câu hỏi này. Đây là những gì SO dành cho.
Danoram

3

trong ngữ cảnh html / js, trên các trình duyệt hiện đại, với các đối tượng có thể lặp khác ngoài Mảng, chúng ta cũng có thể sử dụng [Iterable] .entries ():

for(let [index, element] of document.querySelectorAll('div').entries()) {

    element.innerHTML = '#' + index

}

Có, nó hoạt động, trong khi các phương thức khác được đề cập ở trên bởi @Steven Pribilinskiy, các phương thức DOM khác trả về các đối tượng không có entriesphương thức cho chúng.
matanster

3

Trong một for..ofvòng lặp, chúng ta có thể đạt được điều này thông qua array.entries(). array.entriestrả về một đối tượng iterator Array mới. Một đối tượng iterator biết cách truy cập các mục từ một đối tượng lặp lại tại thời điểm đó, trong khi theo dõi vị trí hiện tại của nó trong chuỗi đó.

Khi next()phương thức được gọi trên các cặp giá trị khóa lặp được tạo. Trong các cặp giá trị khóa này, chỉ số mảng là khóa và mục mảng là giá trị.

let arr = ['a', 'b', 'c'];
let iterator = arr.entries();
console.log(iterator.next().value); // [0, 'a']
console.log(iterator.next().value); // [1, 'b']

Một for..ofvòng lặp về cơ bản là một cấu trúc tiêu thụ một vòng lặp và các vòng lặp thông qua tất cả các phần tử (sử dụng một trình vòng lặp dưới mui xe). Chúng ta có thể kết hợp điều này với array.entries()cách thức sau:

array = ['a', 'b', 'c'];

for (let indexValue of array.entries()) {
  console.log(indexValue);
}


// we can use array destructuring to conveniently
// store the index and value in variables
for (let [index, value] of array.entries()) {
   console.log(index, value);
}


3

Bạn cũng có thể tự xử lý chỉ mục nếu Bạn cần chỉ mục , nó sẽ không hoạt động nếu Bạn cần khóa .

let i = 0;
for (const item of iterableItems) {
  // do something with index
  console.log(i);

  i++;
}

0

Đối với những người sử dụng các đối tượng không phải là một Arrayhoặc thậm chí giống như mảng, bạn có thể xây dựng vòng lặp của riêng mình một cách dễ dàng để bạn vẫn có thể sử dụng for ofcho những thứ localStoragethực sự chỉ có length:

function indexerator(length) {
    var output = new Object();
    var index = 0;
    output[Symbol.iterator] = function() {
        return {next:function() {
            return (index < length) ? {value:index++} : {done:true};
        }};
    };
    return output;
}

Sau đó, chỉ cần cho nó ăn một số:

for (let index of indexerator(localStorage.length))
    console.log(localStorage.key(index))

0

es6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}

5
Câu hỏi là hỏi về một for...ofvòng lặp không phải là mộtfor...in
Áp-ra-ham

3
for...inlà một phần của đặc tả ECMAScript gốc (tức là "es1"). Ngoài ra, lưu ý rằng for...incó nghĩa là lặp đi lặp lại trên các thuộc tính đối tượng. Mặc dù nó có thể lặp qua các mảng, nhưng nó có thể không làm như vậy theo thứ tự dự kiến. Xem thêm trong tài liệu MDN
Boaz

0

Một cách tiếp cận khác có thể được sử dụng Array.prototype.forEach()như

Array.from({
  length: 5
}, () => Math.floor(Math.random() * 5)).forEach((val, index) => {
  console.log(val, index)
})


-6
var fruits = ["apple","pear","peach"];
for (fruit of fruits) {
    console.log(fruits.indexOf(fruit));
    //it shows the index of every fruit from fruits
}

vòng lặp for đi ngang qua mảng, trong khi thuộc tính indexof lấy giá trị của chỉ số khớp với mảng. PD phương pháp này có một số sai sót với số, vì vậy sử dụng trái cây


2
Điều này mất thời gian O (n ^ 2).
Harry

3
Trong trường hợp hiệu suất không quan trọng, điều này vẫn không cung cấp tất cả các chỉ mục chính xác khi có trái cây trùng lặp. Ví dụ, đối với ["apple", "apple", "pear"]các chỉ mục được đưa ra là 0, 0, 2thay vì 0, 1, 2.
trichoplax
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.