Câu hỏi Làm cách nào để xóa một mảng trong JavaScript?


Có cách nào để làm trống mảng và nếu có thể .remove()?

Ví dụ,

A = [1,2,3,4];

Làm thế nào tôi có thể làm trống?


2199
2017-08-05 09:08


gốc


đây là điểm chuẩn với các khả năng khác nhau: jsben.ch/#/7QyI1 - EscapeNetscape


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


Cách xóa một mảng hiện có A:

Phương pháp 1

(đây là câu trả lời ban đầu của tôi cho câu hỏi)

A = [];

Mã này sẽ đặt biến A vào một mảng trống mới. Điều này là hoàn hảo nếu bạn không có tham chiếu đến mảng ban đầu A bất cứ nơi nào khác bởi vì điều này thực sự tạo ra một mảng hoàn toàn mới (trống). Bạn nên cẩn thận với phương thức này bởi vì nếu bạn đã tham chiếu mảng này từ một biến hoặc thuộc tính khác, mảng ban đầu sẽ không thay đổi. Chỉ sử dụng điều này nếu bạn chỉ tham chiếu mảng bằng biến ban đầu của nó A.

Đây cũng là giải pháp nhanh nhất.

Mẫu mã này cho thấy sự cố bạn có thể gặp phải khi sử dụng phương pháp này:

var arr1 = ['a','b','c','d','e','f'];
var arr2 = arr1;  // Reference arr1 by another variable 
arr1 = [];
console.log(arr2); // Output ['a','b','c','d','e','f']

Phương pháp 2 (như đề xuất bởi Matthew Crumley)

A.length = 0

Điều này sẽ xóa mảng hiện có bằng cách thiết lập độ dài của nó thành 0. Một số đã lập luận rằng điều này có thể không hoạt động trong tất cả các triển khai JavaScript, nhưng hóa ra đây không phải là trường hợp. Nó cũng hoạt động khi sử dụng "chế độ nghiêm ngặt" trong ECMAScript 5 vì thuộc tính độ dài của mảng là thuộc tính đọc / ghi.

Phương pháp 3 (như đề xuất bởi Anthony)

A.splice(0,A.length)

Sử dụng .splice() sẽ hoạt động hoàn hảo, nhưng vì .splice() Hàm sẽ trả về một mảng với tất cả các mục đã loại bỏ, nó sẽ thực sự trả về một bản sao của mảng ban đầu. Điểm chuẩn cho thấy điều này không ảnh hưởng đến hiệu suất.

Phương pháp 4 (như đề xuất bởi tanguy_k)

while(A.length > 0) {
    A.pop();
}

Giải pháp này không phải là rất ngắn gọn, và nó cũng là giải pháp chậm nhất, trái với các tiêu chuẩn trước đó được tham chiếu trong câu trả lời ban đầu.

Hiệu suất

Trong tất cả các phương pháp thanh toán bù trừ mảng hiện có, phương pháp 2 và 3 rất giống về hiệu suất và nhanh hơn rất nhiều so với phương pháp 4. Xem phần này điểm chuẩn.

Như được chỉ ra bởi Diadistis trong câu trả lời bên dưới, các điểm chuẩn ban đầu được sử dụng để xác định hiệu suất của bốn phương pháp được mô tả ở trên là không hoàn thiện. Các điểm chuẩn ban đầu tái sử dụng mảng đã xóa để lặp thứ hai là xóa một mảng đã trống.

Điểm chuẩn sau sửa lỗi này: http://jsben.ch/#/hyj65. Nó cho thấy rõ ràng rằng phương pháp # 2 (chiều dài thuộc tính) và # 3 (ghép nối) là phương pháp nhanh nhất (không tính số 1 không thay đổi mảng ban đầu).


Đây là một chủ đề nóng và là nguyên nhân của rất nhiều tranh cãi. Có nhiều câu trả lời đúng và vì câu trả lời này đã được đánh dấu là câu trả lời được chấp nhận trong một thời gian rất dài, tôi sẽ bao gồm tất cả các phương pháp ở đây. Nếu bạn bỏ phiếu cho câu trả lời này, xin vui lòng upvote câu trả lời khác mà tôi đã tham chiếu là tốt.


3457
2017-08-05 09:10



while (A.length) { A.pop(); }, không cần > 0 - Ivan Black
> 0 là IMHO dễ đọc hơn. Và không có sự khác biệt về hiệu suất giữa hai. - Philippe Leybaert
@ daghan, nó không phải là tất cả rõ ràng những gì bạn đang cố gắng để nói. b giữ một tham chiếu đến mảng cũ ngay cả sau khi a được chỉ định một cái mới. c và d tiếp tục tham chiếu cùng một mảng. Do đó, sự khác biệt về kết quả đầu ra được mong đợi. - shovavnik
@DiegoJancic Method # 1 không tính vì nó không xóa mảng. Nó tạo ra một cái mới. Nó không nên được bao gồm trong một điểm chuẩn. - Philippe Leybaert
Bạn không thể sử dụng while(A.pop()) trong trường hợp một mục trong mảng là falsey. Lấy ví dụ A = [2, 1, 0, -1, -2] sẽ cho kết quả A bằng [2, 1]. Cũng while(A.pop() !== undefined) không hoạt động vì bạn có thể có một mảng không xác định là một trong các giá trị. Có lẽ lý do tại sao trình biên dịch không tối ưu hóa nó. - Jonathan Gawrych


Nếu bạn cần giữ mảng ban đầu vì bạn có các tham chiếu khác đến nó cũng cần được cập nhật, bạn có thể xóa nó mà không cần tạo mảng mới bằng cách đặt độ dài của nó thành 0:

A.length = 0;

2253
2017-08-05 16:29



@Acorn Có, nó sẽ hoạt động trên tất cả các trình duyệt. - Matthew Crumley
Tiêu chuẩn ECMAScript 5 nói gì về điều này? - Pacerier
@Pacerier: Nó vẫn hoạt động trong ES5. Từ phần 15.4: "... bất cứ khi nào thuộc tính độ dài được thay đổi, mọi thuộc tính có tên là chỉ mục mảng có giá trị không nhỏ hơn độ dài mới sẽ tự động bị xóa" - Matthew Crumley
@LosManos Ngay cả ở chế độ nghiêm ngặt, length là một tài sản đặc biệt, nhưng không chỉ đọc, vì vậy nó sẽ vẫn hoạt động. - Matthew Crumley
@MattewCrumley Tôi đã thực hiện một số kiểm tra, và nó có vẻ như a.length = 0 không phải là để làm sạch hiệu quả toàn bộ mảng. jsperf.com/length-equal-0-or-new-array Tôi nghĩ rằng nếu bạn có một refence (và bạn đã không bổ sung thêm thuộc tính mà bạn muốn giữ lại), nó là tốt hơn để tạo mảng mới, và lá cũ để thu gom rác, mà sẽ chạy khi thích hợp. - Paul Brewczynski


Ở đây triển khai làm việc nhanh nhất trong khi giữ cùng một mảng ("có thể thay đổi"):

Array.prototype.clear = function() {
  while (this.length) {
    this.pop();
  }
};

FYI Bản đồ định nghĩa clear() vì vậy nó có vẻ hợp lý để có clear() cho Mảng quá.

Hoặc như một Kết hợp giữa Underscore.js:

_.mixin({
  clearArray: function(array) {
    while (array.length) {
      array.pop();
    }
  }
});

Hoặc một hàm đơn giản:

function clearArray(array) {
  while (array.length) {
    array.pop();
  }
}

TypeScript phiên bản:

function clearArray<T>(array: T[]) {
  while (array.length) {
    array.pop();
  }
}

FYI nó không thể được đơn giản hóa để while (array.pop()): các thử nghiệm sẽ thất bại.

Và các bài kiểm tra đi kèm với nó:

describe('Array', () => {
  it('should clear the array', () => {
    let array = [1, 2, 3, 4, 5];
    array.clear();
    expect(array.length).toEqual(0);
    expect(array[0]).toEqual(undefined);
    expect(array[4]).toEqual(undefined);

    // Even with undefined or null inside
    array = [1, undefined, 3, null, 5];
    array.clear();
    expect(array.length).toEqual(0);
    expect(array[0]).toEqual(undefined);
    expect(array[4]).toEqual(undefined);
  });
});

Ở đây cập nhật jsPerf: http://jsperf.com/array-destroy/32  http://jsperf.com/array-destroy/152


256
2018-06-25 20:32



TT câu trả lời của bạn là câu trả lời duy nhất đúng và nhanh (cùng một lúc) nhưng có một số ít "upvotes" ít hơn nhiều. Vâng, có vẻ như những người như các giải pháp khá chậm: / - Ai_boy
@naomik Nhưng đây là một trong những chức năng cơ bản, mà cần phải có được theo mặc định. - thefourtheye
@thefourtheye Giải pháp tốt cho hiệu suất, mặc dù tôi đồng ý với @naomik, bạn không nên sửa đổi các đối tượng gốc. Nói rằng nó nên ở bên cạnh vấn đề, vấn đề là bạn đang sửa đổi globals, điều đó thật tệ. Nếu bạn đang cung cấp mã của mình cho người khác để sử dụng, thì nó sẽ không có tác dụng phụ không lường trước được. Hãy tưởng tượng nếu một thư viện khác cũng thế sửa đổi Array.prototype và nó đã làm một cái gì đó hơi khác nhau, sau đó tất cả trong suốt mã của bạn [].clear() hơi sai. Điều này sẽ không được vui vẻ để gỡ lỗi. Vì vậy, thông điệp chung là: Không sửa đổi globals. - jpillora
@thefourtheye Toàn bộ điểm không sửa đổi phạm vi toàn cầu là bởi vì bạn sẽ không biết nếu mã của người khác đã được (hoặc sẽ) sử dụng tên. Tôi đề nghị một hàm bên trong phạm vi cục bộ. Vì vậy, bên trong ứng dụng của bạn / thư viện của IIFE, làm function clear(arr) { while(arr.length) arr.pop(); }, sau đó xóa mảng bằng clear(arr) thay vì arr.clear(). - jpillora
Hóa ra phương pháp này chậm hơn rất nhiều so với .splice() và .length=0. Các điểm chuẩn không chính xác. Xem câu trả lời cập nhật của tôi. - Philippe Leybaert


Một giải pháp thân thiện hơn và nhiều giải pháp tối ưu hơn sẽ sử dụng splice phương thức để làm trống nội dung của mảng A như sau:

A.splice(0, A.length);


182
2017-11-15 09:49



Tại sao giao diện trình duyệt chéo này thân thiện hơn? Trình duyệt nào có vấn đề với A.length? - stricjux
@ jm2 những gì bạn đang nói là không hoàn toàn đúng sự thật. Nó thực sự sửa đổi các mảng trong câu hỏi và sau đó tất cả các tài liệu tham khảo bị ảnh hưởng. Xem bài kiểm tra trên jsFiddle của tôi: jsfiddle.net/shamasis/dG4PH - Shamasis Bhattacharya
@alex không có nó không, splice sửa đổi mảng và trả về các mục đã xóa. Đọc tài liệu trước: developer.mozilla.org/en-US/docs/JavaScript/Reference/… - David
Chúng tôi có thể ngăn không cho mảng kết quả được trả lại bằng cách sử dụng toán tử dấu phẩy: A.splice(0, A.length),0;. Điều này sẽ để lại giá trị trả lại của 0 giống như A.length = 0; sẽ. Mảng kết quả vẫn được tạo và Nên làm cho tập lệnh chạy chậm hơn: (jsperf ~ 56% chậm hơn). Việc triển khai trình duyệt sẽ ảnh hưởng đến điều này mặc dù tôi không thấy lý do gì splice sẽ nhanh hơn cài đặt length. - Evan Kennedy
Tôi cũng thấy rằng A.splice(0) cũng hoạt động. - corwin.amber


Các câu trả lời mà không có ít hơn 2739 upvotes bây giờ là gây hiểu lầm và không chính xác.

Câu hỏi đặt ra là: "Làm thế nào để bạn làm trống mảng hiện có của bạn?" Ví dụ. cho A = [1,2,3,4].

  1. Nói "A = [] là câu trả lời "là không biết gì và hoàn toàn không chính xác. [] == [] Là sai.

    Điều này là do hai mảng này là hai đối tượng riêng biệt, riêng biệt, với hai bản sắc riêng của chúng, chiếm không gian riêng của chúng trong thế giới số, mỗi riêng của chúng.


Giả sử mẹ bạn yêu cầu bạn dọn sạch thùng rác.

  • Bạn không mang theo một cái mới như thể bạn đã làm những gì bạn đã được yêu cầu.
  • Thay vào đó, bạn dọn sạch thùng rác.
  • Bạn không thay thế một ô đã điền bằng một ô trống mới, và bạn không lấy nhãn "A" từ ô đã điền và dán nhãn vào cái mới như trong A = [1,2,3,4]; A = [];

Làm trống một đối tượng mảng là điều đơn giản nhất bao giờ hết:

A.length = 0;

Bằng cách này, có thể dưới "A" không chỉ trống rỗng, mà còn sạch sẽ như mới!


  1. Hơn nữa, bạn không cần phải loại bỏ thùng rác bằng tay cho đến khi có thể để trống! Bạn được yêu cầu dọn sạch cái hiện tại, hoàn toàn, trong một lượt, không phải nhặt rác cho đến khi thùng có thể rỗng, như trong:

    while(A.length > 0) {
        A.pop();
    }
    
  2. Ngoài ra, để đặt tay trái của bạn ở dưới cùng của thùng rác, giữ nó ở bên phải của bạn ở đầu trang để có thể kéo nội dung của nó ra như trong:

    A.splice(0, A.length);
    

Không, bạn được yêu cầu dọn sạch nó:

A.length = 0;

Đây là mã duy nhất làm trống chính xác nội dung của một mảng JavaScript đã cho.


61
2018-04-30 15:18



Vấn đề duy nhất với giải pháp được đề xuất của bạn là thùng rác vẫn còn tồn tại, nó chỉ là bạn thay đổi bảng thông báo nói rằng không có thùng rác. Tham chiếu đến mảng cũ vẫn tồn tại. Bạn có thể chắc chắn bộ thu gom rác khi thiết lập .length = 0, cũng sẽ loại bỏ tất cả các tham chiếu đến mảng và các thuộc tính của nó? Tôi nghĩ rằng nó mặc dù, nhưng với tôi đó là phép thuật. Một phương thức .clear () là mong muốn để tránh nhầm lẫn để nói rằng ít nhất. - momo
Tôi chưa bao giờ nói rằng giải pháp này là sai. Vấn đề là toàn bộ luồng này hoàn toàn không cần thiết. Hơn 3000 phiếu cho thấy rằng cố gắng tìm ra cách tốt nhất là làm cho nó là một trường hợp đủ hợp lệ cho các nhà phát triển đầu crack của EMCA để thêm một phương pháp như vậy. Không ai phải đi qua tìm ra nó. Có ba - bốn cách khác nhau để làm điều đó. Trong một số điểm chuẩn, các giải pháp độ dài chậm hơn nhiều so với các giải pháp khác. Hơn nữa, ý tưởng thiết lập .length = 0, đối với bất kỳ nhà phát triển hợp lý nào sẽ không phải là một nhà phát triển thỏa đáng. - momo
Bởi vì để thực hiện những gì nó cần, tất cả các tài liệu tham khảo phải được loại bỏ. .length = 0 thậm chí không phải là một cuộc gọi phương thức, vì vậy nếu có các hành động khác được thực hiện khi nó được đặt thành 0 (mà có trong hầu hết các trình duyệt thông qua định nghĩa setter), tôi vẫn sẽ xem xét nó quá kỳ diệu để thực sự tin tưởng nó làm. - momo
Vì vậy, tôi muốn tự mình làm rõ hơn. Một phương pháp rõ ràng có thể được prototyped nhưng đó chỉ là xấu xí. Quan điểm của tôi là việc triển khai này đã có mặt để hơn 10 000 nhà phát triển không phải bỏ ra hàng giờ chỉ đọc chủ đề này, chứ không phải xem xét tất cả những người đã dành nhiều thời gian hơn. - momo
chỉ có một cách để làm trống mảng của bạn, điền vào nó với dữ liệu mới đến và loại bỏ nó một lần nữa. Tất cả những người khác hoặc là không, hoặc là cpu ridiculously không hiệu quả và không thể tha thứ đói. Cách thay thế thực tế duy nhất là A(n) = A.splice( 0, A.length ); trong trường hợp bạn cần phải sao lưu nội dung trước đó của bạn. p.s. Array.length là một thuộc tính đọc-ghi \ trong trường hợp bạn đã bỏ lỡ thực tế cơ bản đó. Có nghĩa là, bạn có thể mở rộng nó đến một chiều dài mới, bạn không thể cắt nó theo chiều dài bạn muốn, và trong số những người khác bạn có thể loại bỏ tất cả các thành viên bằng cách rút ngắn chiều dài của nó thành 0. Đó là một con dao Thụy Sĩ của mảng. - Bekim Bacaj


Kiểm tra hiệu suất:

http://jsperf.com/array-clear-methods/3

a = []; // 37% slower
a.length = 0; // 89% slower
a.splice(0, a.length)  // 97% slower
while (a.length > 0) {
    a.pop();
} // Fastest

59
2018-05-14 07:14



Việc thêm các thay đổi phần trăm sẽ sử dụng nhiều mà không cần chú ý đến nền tảng của bạn. Trên máy pop của tôi chỉ nhanh hơn rất nhiều trong Chrome 34 nhưng thực sự chậm hơn [] trong Firefox mới nhất. - Matt Styles
Thử nghiệm trong Firefox 39.0 32 bit trên Windows NT 6.3 64 bit, a = [] là nhanh nhất! - Reza-S4
Chắc chắn có điều gì đó đáng sợ trong kết quả thử nghiệm này dưới Chrome. Làm thế nào trong địa ngục có thể popping loop được nhanh hơn nhiều sau đó 3 giải pháp khác? - chqrlie
@chqrlie Nó không phải. Đó là phương pháp chậm nhất. Kiểm tra điểm chuẩn là thiếu sót. - Philippe Leybaert
Vui lòng xóa câu trả lời này vì câu trả lời sai và liên kết đến một bài kiểm tra thiếu sót vô nghĩa làm bằng chứng giả. - James Wakefield


Bạn có thể thêm điều này vào tệp JavaScript của mình để cho phép các mảng của bạn bị "xóa":

Array.prototype.clear = function() {
    this.splice(0, this.length);
};

Sau đó, bạn có thể sử dụng nó như thế này:

var list = [1, 2, 3];
list.clear();

Hoặc nếu bạn muốn chắc chắn bạn không phá hủy điều gì đó:

if (!Array.prototype.clear) {
    Array.prototype.clear = function() {
       this.splice(0, this.length);
    };
}

Rất nhiều người nghĩ rằng bạn không nên sửa đổi các đối tượng bản địa (như Array), và tôi có khuynh hướng đồng ý. Vui lòng thận trọng khi quyết định cách xử lý việc này.


32
2017-12-11 02:58



@naomik Bạn có thể giải thích lý do của bạn tại sao làm một điều như vậy là cau mày? - Undefined
Nó được "cau mày" để sửa đổi các hàm nguyên thủy javascript như Array và String. Bạn có thể có thể là quá tải một chức năng đã tồn tại và thùng rác lớp đối tượng. Có thể có một công cụ javascript mơ hồ đã rõ ràng () và hy vọng nó hoạt động theo một cách khác. Tread cẩn thận là tất cả những gì tôi nói. - Design by Adrian
Làm thế nào về vấn đề mà làm một foreach qua các thành viên của một mảng sẽ đột nhiên bắt đầu bao gồm một clear Chìa khóa? - ErikE
Như một tài liệu tham khảo: Tại sao mở rộng đối tượng gốc là một thực tiễn không tốt? - Emile Bergeron


Array.prototype.clear = function() {
    this.length = 0;
};

Và gọi nó là: array.clear();


16
2018-02-22 21:28



Vui lòng không khuyến khích sửa đổi các đối tượng gốc. - user633183
tại sao mọi người có xu hướng này để lấy câu trả lời được chấp nhận và đặt nó vào một chức năng nguyên mẫu? Bạn có thực sự làm điều này trong các dự án của mình không? Bạn có một thư viện khổng lồ về các bổ sung nguyên mẫu mà bạn đưa vào trong mọi dự án không? - nurettin
Tại sao không chỉ nhập mảng.length = 0? - Design by Adrian
@naomik "Xin vui lòng không khuyến khích sửa đổi các đối tượng bản địa." - Tôi hoàn toàn đồng ý với điều này, nhưng chỉ lặp đi lặp lại câu đó là tự kiêu ngạo. Một người nào đó đề xuất giải pháp như vậy có thể không nhận thức được hậu quả và thả dòng này vào chúng thay vì cung cấp giải thích ngắn hoặc liên kết không truyền đạt ý nghĩa nào khác ngoài "chúng tôi, những người thông minh hơn bạn, bảo bạn đừng làm điều này, bởi vì chúng tôi biết rõ hơn". - John Weisz
Như một tài liệu tham khảo: Tại sao mở rộng đối tượng gốc là một thực tiễn không tốt? - Emile Bergeron