Array.prototype.includes so với Array.prototype.indexOf


112

Ngoài khả năng đọc được cải thiện, có lợi thế nào để includesvượt qua indexOfkhông? Họ có vẻ giống hệt tôi.

Sự khác biệt giữa điều này là gì

var x = [1,2,3].indexOf(1) > -1; //true

Và điều này?

var y = [1,2,3].includes(1); //true

12
includescó hỗ trợ trình duyệt kém hơn nhiều.
Quentin

4
Lưu ý rằng đó includeskhông phải là một phần của ES6 / ES2015. Đây là một đề xuất cho phiên bản tiếp theo của ECMAScript và sẽ được bổ sung trong năm nay.
Felix Kling

4
cũng chỉ muốn đề cập rằng includesKHÔNG được hỗ trợ trong IE
ZvKa

Câu trả lời:


138

tl; dr: NaN được xử lý khác nhau:

  • [NaN].indexOf(NaN) > -1false
  • [NaN].includes(NaN)true

Từ đề xuất :

Động lực

Khi sử dụng mảng ECMAScript, người ta thường muốn xác định xem mảng có bao gồm một phần tử hay không. Mô hình phổ biến cho điều này là

if (arr.indexOf(el) !== -1) {
    ...
}

với nhiều khả năng khác, ví dụ arr.indexOf(el) >= 0, hoặc thậm chí ~arr.indexOf(el).

Những mẫu này thể hiện hai vấn đề:

  • Họ không "nói được ý của bạn": thay vì hỏi về việc liệu mảng có bao gồm một phần tử hay không, bạn hỏi chỉ số của lần xuất hiện đầu tiên của phần tử đó trong mảng là gì, sau đó so sánh nó hoặc chỉnh sửa nó, để xác định câu trả lời cho câu hỏi thực tế của bạn.
  • Chúng thất bại NaNindexOfsử dụng So sánh bình đẳng nghiêm ngặt và do đó [NaN].indexOf(NaN) === -1.

Giải pháp đề xuất

Chúng tôi đề xuất bổ sung một Array.prototype.includesphương pháp, sao cho các mẫu trên có thể được viết lại thành

if (arr.includes(el)) {
    ...
}

Điều này có ngữ nghĩa gần như tương tự như ở trên, ngoại trừ việc nó sử dụng thuật toán so sánh SameValueZero thay vì So sánh bình đẳng nghiêm ngặt, do đó làm cho [NaN].includes(NaN)đúng.

Do đó, đề xuất này giải quyết được cả hai vấn đề được thấy trong mã hiện có.

Chúng tôi cũng thêm một fromIndextham số, tương tự như Array.prototype.indexOfString.prototype.includes, để nhất quán.


Thêm thông tin:


1
Chỉ một nửa sự thật. Cũng khác: các phần tử bị thiếu được coi là undefinedbởi .includes()và không được coi là bởi .indexOf().
Robert Siemer ngày

11

Nếu bạn thắc mắc về hiệu suất, hiện tại, indexOf nhanh hơn, nhưng thử nghiệm JSperf này có xu hướng cho thấy rằng thời gian trôi qua nhiều hơn includes()sẽ nhanh hơn indexOf(tôi đoán nó sẽ được tối ưu hóa hơn nữa).

IMHO, tôi cũng thích viết if (arr.includes(el)) {}vì nó rõ ràng hơn và dễ bảo trì hơnif (arr.indexOf(el) !== -1) {}


1
Có vẻ như sự khác biệt về hiệu suất là không quá rõ ràng. Firefox di động của tôi cho thấy rằng indexOf thực sự nhanh hơn. Một số phiên bản Chrome hoạt động giống nhau ... Nhưng dù sao thì sự khác biệt dường như không đáng kể trong các triển khai ngày nay.
Nux

8

.indexOf().includes()các phương thức có thể được sử dụng để tìm kiếm một phần tử trong một mảng hoặc để tìm kiếm một ký tự / chuỗi con trong một chuỗi đã cho.

Sử dụng trong mảng

( Liên kết đến Đặc tả ECMAScript)

  1. indexOfsử dụng So sánh bình đẳng nghiêm ngặt trong khi includessử dụng thuật toán SameValueZero . Bởi vì lý do này, hai điểm khác biệt sau đây phát sinh.

  2. Như đã chỉ ra bởi Felix Kling , hành vi là khác nhau trong trường hợp NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Các hành vi cũng khác nhau trong trường hợp undefined.
let arr = [ , , ];

arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true

Sử dụng trong chuỗi

( Liên kết đến Đặc tả ECMAScript)

  1. Nếu bạn chuyển một RegExp tới indexOf, nó sẽ coi RegExp là một chuỗi và sẽ trả về chỉ mục của chuỗi, nếu được tìm thấy. Tuy nhiên, nếu bạn chuyển một RegExp tới includes, nó sẽ đưa ra một ngoại lệ.
let str = "javascript";

str.indexOf(/\w/); // returns -1 even though the elements match the regex because /\w/ is treated as string
str.includes(/\w/); // throws TypeError: First argument to String.prototype.includes must not be a regular expression

Hiệu suất

Như 538ROMEO đã chỉ ra, includescó thể chậm hơn một chút (rất nhỏ) một chút (vì nó cần kiểm tra regex làm đối số đầu tiên) so với indexOfnhưng trên thực tế, điều này không tạo ra nhiều khác biệt và không đáng kể.

Lịch sử

String.prototype.includes()đã được giới thiệu trong ECMAScript 2015 trong khi Array.prototype.includes()được giới thiệu trong ECMAScript 2016. Liên quan đến hỗ trợ trình duyệt, hãy sử dụng chúng một cách khôn ngoan.

String.prototype.indexOf()Array.prototype.indexOf()có mặt trong phiên bản ES5 của ECMAScript và do đó được hỗ trợ bởi tất cả các trình duyệt.


indexOfđưa ra truesau khi thiết lập rõ ràng undefinedthành một mảng: let arr=[undefined];hoặc let arr=[];arr[0]=undefined;Bây giờarr.indexOf(undefined) === 0
Jay Dadhania

Bạn là người duy nhất chỉ ra sự khác biệt với undefined: Lý do là .includesxử lý các phần tử bị thiếu là undefined, trong khi .indexOf()bỏ qua chúng. Bạn cũng có thể "tạo" các phần tử bị thiếu với arr[number beyond length] = whatever.
Robert Siemer ngày

Không ai yêu cầu chuỗi, nhưng nhận xét của bạn cho thấy rằng .includes()chỉ ăn chuỗi. Trong thực tế, cả hai phương pháp đều ép buộc bất cứ thứ gì vào một chuỗi tốt nhất có thể. Regex được đặc biệt loại trừ như là đối số để .includes()để cho phép bổ sung trong tương lai để tiêu chuẩn theo quy định của dự thảo hiện hành.
Robert Siemer ngày

4

Về mặt khái niệm, bạn nên sử dụng indexOf khi bạn muốn sử dụng vị trí indexOf chỉ cung cấp cho bạn để trích xuất giá trị hoặc hoạt động trên mảng, tức là sử dụng slice, shift hoặc split sau khi bạn đã có vị trí của phần tử. Mặt khác, Sử dụng Array.includes chỉ để biết giá trị có nằm trong mảng chứ không phải vị trí vì bạn không quan tâm đến nó.


0

indexOf()includes()cả hai đều có thể được sử dụng để tìm các phần tử trong một mảng, tuy nhiên mỗi hàm mang lại các giá trị trả về khác nhau.

indexOftrả về một số ( -1nếu phần tử không có trong mảng hoặc vị trí mảng nếu phần tử có mặt).

includes()trả về giá trị boolean ( truehoặc false).


Xin chào Kruti, câu hỏi này đã được trả lời và nó có một câu trả lời được chấp nhận. Hơn nữa, bạn có thể thấy câu trả lời của mình chỉ chứa thông tin đã được nói trong các câu trả lời khác. Câu hỏi, cuối cùng thì cũng đã 4 năm rồi. Vui lòng cung cấp hướng dẫn về những câu hỏi mới nhất hoặc những câu hỏi chưa được trả lời. Cảm ơn bạn
leonardfactory
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.