TypeScript cho bằng chỉ mục / khóa?


146

Như được mô tả ở đây, TypeScript giới thiệu một vòng lặp foreach:

var someArray = [9, 2, 5];
for (var item of someArray) {
    console.log(item); // 9,2,5
}

Nhưng không có chỉ số / khóa nào? Tôi mong đợi một cái gì đó như:

for (var item, key of someArray) { ... }

Câu trả lời:


274

.forEach đã có khả năng này:

const someArray = [9, 2, 5];
someArray.forEach((value, index) => {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
});

Nhưng nếu bạn muốn các khả năng của for...of, thì bạn có thể mapmảng đến chỉ mục và giá trị:

for (const { index, value } of someArray.map((value, index) => ({ index, value }))) {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
}

Điều đó hơi dài, vì vậy có thể giúp đưa nó vào một chức năng có thể sử dụng lại:

function toEntries<T>(a: T[]) {
    return a.map((value, index) => [index, value] as const);
}

for (const [index, value] of toEntries(someArray)) {
    // ..etc..
}

Phiên bản lặp lại

Điều này sẽ hoạt động khi nhắm mục tiêu ES3 hoặc ES5 nếu bạn biên dịch với --downlevelIterationtùy chọn trình biên dịch.

function* toEntries<T>(values: T[] | IterableIterator<T>) {
    let index = 0;
    for (const value of values) {
        yield [index, value] as const;
        index++;
    }
}

Array.prototype.entries () - ES6 +

Nếu bạn có thể nhắm mục tiêu môi trường ES6 + thì bạn có thể sử dụng .entries()phương pháp như được nêu trong câu trả lời của Arnavion .


Nhưng TypeScript biên dịch "for ... of" thành "for" đơn giản có chỉ số var _i. Vì vậy, thật dễ dàng cho các nhà phát triển TypeScript cho phép chúng tôi sử dụng _i này. Xem ví dụ về sân chơi: bit.ly/1R9SfBR
Mick

2
@Mick nó phụ thuộc vào mục tiêu. Khi dịch mã sang ES6, nó không làm điều đó. Lý do cho mã bổ sung đó khi dịch mã chỉ là để mã ES6 hoạt động trong các phiên bản trước.
David Sherret

3
Làm thế nào bạn có thể làm một nghỉ ngơi; trong đó cho ai?
João Silva

Ngoài ra, một câu trả lời tốt stackoverflow.com/questions
432348937/ Kiếm

@ JoãoSilva bạn có thể sử dụng Array.some()và trả về false ở lần lặp bạn muốn dừng. Nó gần như không rõ ràng hoặc đẹp như một breaknhưng nó sẽ hoàn thành công việc. Cá nhân tôi không thích nó, có lẽ tôi sẽ viết lại phép lặp theo một cách khác :) xem stackoverflow.com/questions/2641347/
Kẻ

36

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries

for (var [key, item] of someArray.entries()) { ... }

Trong TS, điều này yêu cầu nhắm mục tiêu ES2015 vì nó yêu cầu thời gian chạy để hỗ trợ các trình vòng lặp , điều mà các thời gian chạy ES5 không có. Tất nhiên bạn có thể sử dụng một cái gì đó như Babel để làm cho đầu ra hoạt động trên thời gian chạy ES5.


35

"Javascript trường học cũ" để giải cứu (cho những người không quen thuộc / yêu thích lập trình chức năng)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}

2
Tôi thực sự thích câu trả lời này là tốt nhất. Không sử dụng các phương thức bổ sung chỉ để tạo một chỉ mục cho mỗi phần tử.
bluegrounds

Cảm ơn youuu rấtyyy muuuchh! Chúng tôi không biết điều này :)
TSR

14

Bạn có thể sử dụng toán tử TypeScript trong for..in để truy cập chỉ mục khi xử lý các bộ sưu tập.

var test = [7,8,9];
for (var i in test) {
   console.log(i + ': ' + test[i]);
} 

Đầu ra:

 0: 7
 1: 8
 2: 9

Xem bản demo


Xin lưu ý rằng "i" là một chuỗi không phải là một int với vòng lặp for..in. Thực hiện phép toán số học với "i" sẽ dẫn đến nối chuỗi. (i + 1) sẽ bằng "01" chẳng hạn khi i = 0
Stéphane

for..incũng có thể cung cấp cho bạn nhiều hơn bạn mong đợi vì nó cũng bao gồm tất cả các hàm được khai báo trên một đối tượng. Ví dụ:for (var prop in window.document) { console.log(prop); }
Ken Lyon

5

Hoặc một giải pháp trường học cũ khác:

var someArray = [9, 2, 5];
let i = 0;
for (var item of someArray) {
    console.log(item); // 9,2,5
    i++;
}
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.