ฉันจะล้างอาร์เรย์ใน JavaScript ได้อย่างไร


2197

มีวิธีว่างอาเรย์และถ้าเป็นเช่นนั้นด้วย.remove()?

ตัวอย่างเช่น

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

ฉันจะล้างสิ่งนั้นได้อย่างไร


1
มาตรฐานที่นี่มีความเป็นไปได้ที่แตกต่างกัน: jsben.ch/#/7QyI1
EscapeNetscape

คำตอบ:


4413

วิธีล้างอาร์เรย์ที่มีอยู่A:

วิธีที่ 1

(นี่เป็นคำตอบเดิมของฉันสำหรับคำถาม)

A = [];

รหัสนี้จะตั้งค่าตัวแปรAเป็นอาร์เรย์ว่างใหม่ นี่คือที่สมบูรณ์แบบถ้าคุณไม่มีการอ้างอิงไปยังอาร์เรย์เดิมAที่อื่นเพราะมันจะสร้างอาร์เรย์ใหม่ (ว่าง) ใหม่ คุณควรระวังด้วยวิธีนี้เพราะถ้าคุณได้อ้างอิงอาเรย์นี้จากตัวแปรหรือคุณสมบัติอื่นอาเรย์ดั้งเดิมจะไม่เปลี่ยนแปลง ใช้สิ่งนี้เฉพาะเมื่อคุณอ้างอิงอาร์เรย์ด้วยตัวแปรดั้งเดิมAเท่านั้น

นี่เป็นวิธีที่เร็วที่สุด

ตัวอย่างโค้ดนี้แสดงปัญหาที่คุณสามารถพบได้เมื่อใช้วิธีนี้:

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']

วิธีที่ 2 ( แนะนำโดยMatthew Crumley )

A.length = 0

สิ่งนี้จะล้างอาเรย์ที่มีอยู่โดยการตั้งค่าความยาวเป็น 0 บางคนแย้งว่านี่อาจไม่ทำงานในการนำไปใช้ของ JavaScript ทั้งหมด แต่ปรากฎว่าไม่ใช่กรณีนี้ นอกจากนี้ยังทำงานเมื่อใช้ "โหมดเข้มงวด" ใน ECMAScript 5 เพราะคุณสมบัติความยาวของอาร์เรย์เป็นคุณสมบัติอ่าน / เขียน

วิธีที่ 3 ( แนะนำโดยAnthony )

A.splice(0,A.length)

การใช้.splice()จะทำงานได้อย่างสมบูรณ์ แต่เนื่องจาก.splice()ฟังก์ชั่นจะส่งกลับอาร์เรย์พร้อมกับรายการที่ถูกลบทั้งหมดมันจะคืนค่าสำเนาของอาร์เรย์ดั้งเดิม เกณฑ์มาตรฐานชี้ให้เห็นว่าสิ่งนี้ไม่มีผลกระทบต่อประสิทธิภาพการทำงาน แต่อย่างใด

วิธีที่ 4 (ตามที่แนะนำโดยtanguy_k )

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

คำตอบนี้ไม่รวบรัดมากและเป็นคำตอบที่ช้าที่สุดซึ่งตรงกันข้ามกับการวัดเปรียบเทียบก่อนหน้าซึ่งอ้างอิงในคำตอบดั้งเดิม

ประสิทธิภาพ

ในวิธีการล้างอาเรย์ที่มีอยู่ทั้งหมดวิธีที่ 2 และ 3 นั้นคล้ายคลึงกันมากในประสิทธิภาพและเร็วกว่าวิธีที่ 4 มากดูเกณฑ์มาตรฐานนี้

ดังที่Diadistis ได้กล่าวไว้ในคำตอบด้านล่างเกณฑ์มาตรฐานดั้งเดิมที่ใช้ในการกำหนดประสิทธิภาพของวิธีการทั้งสี่ที่อธิบายไว้ข้างต้นนั้นมีข้อบกพร่อง มาตรฐานเดิมนำอาเรย์ที่ผ่านการล้างมาใช้ซ้ำเพื่อให้การทำซ้ำครั้งที่สองเป็นการล้างอาเรย์ที่ว่างเปล่าไปแล้ว

มาตรฐานดังต่อไปนี้ช่วยแก้ไขข้อบกพร่องนี้: http://jsben.ch/#/hyj65 มันแสดงให้เห็นอย่างชัดเจนว่าวิธีที่ # 2 (คุณสมบัติความยาว) และ # 3 (splice) เป็นวิธีที่เร็วที่สุด (ไม่ใช่วิธีการนับ # 1 ซึ่งไม่ได้เปลี่ยนอาร์เรย์เดิม)


นี่เป็นประเด็นร้อนแรงและเป็นต้นเหตุของความขัดแย้งมากมาย จริงๆแล้วมีหลายคำตอบที่ถูกต้องและเนื่องจากคำตอบนี้ถูกทำเครื่องหมายว่าเป็นคำตอบที่ได้รับการยอมรับมาเป็นเวลานานฉันจะรวมวิธีการทั้งหมดที่นี่ หากคุณลงคะแนนสำหรับคำตอบนี้โปรดลบคำตอบอื่น ๆ ที่ฉันได้อ้างถึงด้วย


184
while (A.length) { A.pop(); }, ไม่ต้องการ> 0
Ivan Black

327
> 0สามารถอ่านได้มากขึ้น IMHO และไม่มีความแตกต่างด้านประสิทธิภาพระหว่างสองอย่างนี้
Philippe Leybaert

10
@ ดาแกนมันไม่ชัดเจนเลยในสิ่งที่คุณพยายามจะพูด bเก็บการอ้างอิงไปยังอาเรย์เก่าแม้หลังจากaกำหนดใหม่ cและdดำเนินการอ้างอิงอาเรย์ต่อไป ความแตกต่างในผลลัพธ์จึงคาดว่า
shovavnik

9
@DiegoJancic วิธี # 1 ไม่นับเพราะไม่ได้ล้างอาร์เรย์ มันสร้างขึ้นมาใหม่ ไม่ควรรวมอยู่ในเกณฑ์มาตรฐาน
Philippe Leybaert

44
คุณไม่สามารถใช้while(A.pop())ในกรณีที่รายการในอาร์เรย์เป็นเท็จ ยกตัวอย่างเช่น A = [2, 1, 0, -1, -2] จะส่งผลให้ A เท่ากับ [2, 1] แม้while(A.pop() !== undefined)จะไม่ทำงานเพราะคุณสามารถมีอาร์เรย์ที่ไม่ได้กำหนดเป็นหนึ่งในค่า อาจเป็นสาเหตุที่คอมไพเลอร์ไม่ปรับให้เหมาะสม
Jonathan Gawrych

2459

หากคุณต้องการเก็บอาร์เรย์เดิมไว้เพราะคุณมีการอ้างอิงอื่น ๆ ที่ควรปรับปรุงเช่นกันคุณสามารถล้างมันได้โดยไม่ต้องสร้างอาร์เรย์ใหม่โดยการตั้งค่าความยาวเป็นศูนย์:

A.length = 0;

17
ECMAScript 5 Standard บอกอะไรเกี่ยวกับเรื่องนี้
Pacerier

212
@Pacerier: มันยังใช้งานได้ใน ES5 จากส่วนที่ 15.4: "... เมื่อใดก็ตามที่มีการเปลี่ยนแปลงคุณสมบัติความยาวคุณสมบัติทุกรายการที่มีชื่อคือดัชนีอาร์เรย์ที่ค่าไม่น้อยกว่าความยาวใหม่จะถูกลบโดยอัตโนมัติ"
Matthew Crumley

2
@einar: อาร์เรย์ JavaScript ขยายเสมอเพื่อให้พอดีกับสิ่งที่คุณใส่ไว้ดังนั้นเมื่อคุณเรียกmyarray.push(whatever)มันจะเพิ่มหนึ่งความยาว ดังนั้นการตั้งค่าความยาวจะตัดทอนอาร์เรย์ แต่ไม่ถาวร
Matthew Crumley

12
@ LosManos แม้ในโหมดเข้มงวดlengthเป็นคุณสมบัติพิเศษ แต่ไม่ได้อ่านอย่างเดียวดังนั้นจึงยังคงใช้งานได้
Matthew Crumley

11
@ MattewCrumley ฉันได้ทำการทดสอบและดูเหมือนว่า a.length = 0 ไม่ใช่การล้างอาเรย์ทั้งหมด jsperf.com/length-equal-0-or-new-arrayฉันคิดว่าถ้าคุณมีหนึ่ง refence (และคุณยังไม่ได้เพิ่มคุณสมบัติพิเศษที่คุณต้องการเก็บไว้) มันจะดีกว่าที่จะสร้างอาร์เรย์ใหม่และปล่อยให้เก่า ตัวรวบรวมขยะที่จะทำงานเมื่อเหมาะสม
Paul Brewczynski

289

นี่คือการใช้งานที่เร็วที่สุดในขณะที่ยังคงอาร์เรย์เหมือนเดิม ("ไม่แน่นอน"):

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

FYI ไม่สามารถทำให้ง่ายขึ้นได้while (array.pop()): การทดสอบจะล้มเหลว

FYI MapและSet define clear()ดูเหมือนจะมีเหตุผลclear()สำหรับArrayเช่นกัน

เวอร์ชั่นของ TypeScript:

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

การทดสอบที่เกี่ยวข้อง:

describe('clearArray()', () => {
  test('clear regular array', () => {
    const array = [1, 2, 3, 4, 5];
    clearArray(array);
    expect(array.length).toEqual(0);
    expect(array[0]).toEqual(undefined);
    expect(array[4]).toEqual(undefined);
  });

  test('clear array that contains undefined and null', () => {
    const array = [1, undefined, 3, null, 5];
    clearArray(array);
    expect(array.length).toEqual(0);
    expect(array[0]).toEqual(undefined);
    expect(array[4]).toEqual(undefined);
  });
});

นี่คือ jsPerf ที่อัปเดตแล้ว: http://jsperf.com/array-destroy/32 http://jsperf.com/array-destroy/152


5
TT คำตอบของคุณเป็นคำตอบเดียวที่ถูกต้องและรวดเร็ว (ในเวลาเดียวกัน) แต่มี "upvotes" น้อยกว่ามาก ดูเหมือนว่าคนชอบวิธีแก้ปัญหาที่ค่อนข้างช้า: /
obenjiro

@naomik แต่นี่เป็นหนึ่งในฟังก์ชันพื้นฐานซึ่งควรจะมีโดยค่าเริ่มต้น
thefourtheye

7
@thefourtheye วิธีแก้ปัญหาที่ดีสำหรับประสิทธิภาพแม้ว่าฉันเห็นด้วยกับ @naomik คุณไม่ควรแก้ไขวัตถุในตัว การบอกว่ามันควรจะอยู่ข้างๆจุดปัญหาคือคุณกำลังปรับเปลี่ยนวงกลมซึ่งไม่ดี หากคุณให้รหัสของคุณเพื่อให้ผู้อื่นใช้งานคุณควรไม่มีผลข้างเคียงที่ไม่คาดคิด ลองคิดดูหากห้องสมุดอีกนอกจากนี้ยังมีการปรับเปลี่ยนArray.prototypeและมันก็ทำสิ่งที่แตกต่างกันเล็กน้อยแล้วทั่วรหัสของคุณ[].clear()เป็นความผิดเล็กน้อย การแก้จุดบกพร่องนี้จะไม่สนุก ดังนั้นข้อความทั่วไปคือ: อย่าแก้ไข globals
jpillora

3
@thefourtheye จุดรวมของการไม่แก้ไขขอบเขตส่วนกลางนั้นเป็นเพราะคุณไม่รู้ว่ารหัสของบุคคลอื่นนั้นใช้ชื่อนี้อยู่แล้ว (หรือจะเป็น) ฉันแนะนำฟังก์ชั่นภายในขอบเขตท้องถิ่น ดังนั้นภายในโปรแกรมประยุกต์ของคุณ / ห้องสมุดIIFEทำfunction clear(arr) { while(arr.length) arr.pop(); }แล้วอาร์เรย์ชัดเจนกับแทนclear(arr) arr.clear()
jpillora

2
มันกลับกลายเป็นว่าวิธีนี้ช้ากว่า.splice()และ.length=0มาก มาตรฐานไม่ถูกต้อง ดูคำตอบที่อัปเดตของฉัน
Philippe Leybaert

216

โซลูชันที่เป็นมิตรข้ามเบราว์เซอร์และเหมาะสมที่สุดจะใช้spliceวิธีการล้างเนื้อหาของอาร์เรย์ A ดังต่อไปนี้:

A.splice(0, A.length);


49
เหตุใดจึงข้ามเบราว์เซอร์ที่เป็นมิตรมากกว่านี้ เบราว์เซอร์ใดที่มีปัญหากับ A.length
stricjux

4
@ jm2 สิ่งที่คุณพูดไม่เป็นความจริงเลย มันปรับเปลี่ยนอาร์เรย์ที่เป็นปัญหาและจากนั้นการอ้างอิงทั้งหมดจะได้รับผลกระทบ ดูการทดสอบบน jsFiddle ของฉัน: jsfiddle.net/shamasis/dG4PH
Shamasis Bhattacharya

3
@alex ไม่มันไม่ได้spliceปรับเปลี่ยนอาร์เรย์และส่งกลับรายการที่ถูกลบ อ่านเอกสารก่อน: developer.mozilla.org/en-US/docs/JavaScript/Reference/ …
David Hellsing

3
เราสามารถป้องกันไม่ให้อาร์เรย์ที่เกิดจากการถูกส่งกลับโดยใช้ประกอบจุลภาคA.splice(0, A.length),0; : นี้จะปล่อยให้ค่าตอบแทนของ0เช่นเดียวกับที่A.length = 0;จะ อาร์เรย์ผลลัพธ์ยังคงถูกสร้างและควรทำให้สคริปต์ทำงานช้าลง: ( jsperf ~ 56% ช้าลง) การใช้งานเบราว์เซอร์จะส่งผลกระทบนี้ แต่ผมไม่เห็นเหตุผลว่าทำไมจะเร็วกว่าการตั้งค่าsplice length
Evan Kennedy

8
ฉันยังพบว่าเพิ่งใช้A.splice(0)งานได้
corwin.amber

97

คำตอบที่มีจำนวน 2739 upvotes ในตอนนี้ทำให้เข้าใจผิดและไม่ถูกต้อง

คำถามคือ: "คุณจะล้างอาร์เรย์ที่มีอยู่ของคุณได้อย่างไร" A = [1,2,3,4]เช่นสำหรับ

  1. การพูดว่า " A = []คือคำตอบ" นั้นไม่รู้และไม่ถูกต้องอย่างแน่นอน [] == []เป็นเท็จ

    นี่เป็นเพราะทั้งสองอาร์เรย์นั้นแยกจากกันเป็นสองชิ้นโดยแต่ละชิ้นจะมีตัวตนสองตัวซึ่งใช้พื้นที่ของตัวเองในโลกดิจิตอลแต่ละตัวเป็นของตัวเอง


สมมติว่าแม่ของคุณขอให้คุณล้างถังขยะ

  • คุณจะไม่นำสิ่งใหม่เข้ามาราวกับว่าคุณได้ทำสิ่งที่คุณขอมาแล้ว
  • แต่คุณล้างถังขยะแทน
  • คุณไม่ได้แทนที่กระป๋องที่เติมด้วยกระป๋องเปล่าใหม่และคุณไม่ได้ใช้ป้ายกำกับ "A" จากกระป๋องที่บรรจุแล้วและติดกับกระป๋องใหม่ตามที่ A = [1,2,3,4]; A = [];

การล้างวัตถุอาร์เรย์เป็นสิ่งที่ง่ายที่สุด:

A.length = 0;

วิธีนี้ความสามารถภายใต้ "A" ไม่เพียง แต่ว่างเปล่า แต่ยังสะอาดเหมือนใหม่!


  1. นอกจากนี้คุณไม่จำเป็นต้องลบขยะด้วยมือจนกว่ากระป๋องจะว่างเปล่า! คุณถูกขอให้ล้างสิ่งที่มีอยู่ทั้งหมดในคราวเดียวเพื่อไม่ให้ไปทิ้งถังขยะจนกว่าจะว่างเปล่าได้ดังใน:

    while(A.length > 0) {
        A.pop();
    }
  2. และไม่ควรวางมือซ้ายไว้ที่ด้านล่างของถังขยะโดยถือไว้ที่ด้านบนขวาเพื่อดึงเนื้อหาออกมาดังเช่น:

    A.splice(0, A.length);

ไม่คุณถูกขอให้ล้างมัน:

A.length = 0;

นี่เป็นรหัสเดียวที่ทำให้เนื้อหาในอาร์เรย์ JavaScript ที่ระบุนั้นถูกต้อง


11
ปัญหาเดียวของวิธีแก้ไขปัญหาที่แนะนำคือถังขยะยังคงมีอยู่เพียงแค่คุณเปลี่ยนกระดานแจ้งเตือนที่แจ้งว่าไม่มีถังขยะ การอ้างอิงไปยังอาร์เรย์เก่าควรยังคงมีอยู่ คุณแน่ใจได้หรือไม่ว่าตัวรวบรวมขยะเมื่อตั้งค่า. long = 0 จะลบการอ้างอิงทั้งหมดไปยังอาร์เรย์และคุณสมบัติของอาร์เรย์ด้วยหรือไม่ ฉันคิดว่ามันทำ แต่สำหรับฉันนั่นคือเวทมนตร์ A. ชัดเจน () วิธีการเป็นที่พึงประสงค์เพื่อหลีกเลี่ยงความสับสนที่จะพูดอย่างน้อย
mmm

8
ฉันไม่เคยระบุว่าวิธีนี้ผิด ปัญหาคือว่าด้ายทั้งหมดนี้ไม่จำเป็นอย่างสมบูรณ์ การโหวตมากกว่า 3000 ครั้งแสดงให้เห็นว่าการพยายามคิดออกว่าวิธีที่ดีที่สุดควรทำให้เป็นกรณีที่ถูกต้องเพียงพอสำหรับนักพัฒนา crack head EMCA เพื่อเพิ่มวิธีดังกล่าว ไม่ควรมีใครที่จะคิดออก มีวิธีที่แตกต่างกันสามถึงสี่วิธี ในการวัดประสิทธิภาพการแก้ปัญหาความยาวนั้นช้ากว่าตัวอื่น ๆ มาก นอกจากนี้แนวคิดของการตั้งค่า. long = 0 สำหรับนักพัฒนาที่สมเหตุสมผลจะไม่เป็นที่น่าพอใจ
mmm

2
เนื่องจากเพื่อให้บรรลุผลตามที่ควรจะต้องลบการอ้างอิงทั้งหมด .length = 0 ไม่ได้เรียกใช้เมธอดดังนั้นหากมีการดำเนินการอื่นเมื่อตั้งค่าเป็น 0 (ซึ่งมีในเบราว์เซอร์ส่วนใหญ่ผ่าน setter กำหนด) ฉันจะยังคงคิดว่ามันน่าอัศจรรย์เกินกว่าที่จะเชื่อในสิ่งที่มันควร ทำ.
mmm

7
ดังนั้นฉันค่อนข้างชัดเจนว่าตัวเอง วิธีการที่ชัดเจนสามารถสร้างต้นแบบได้ แต่นั่นก็น่าเกลียด ประเด็นของฉันคือการดำเนินการนี้ควรมีอยู่แล้วเพื่อให้นักพัฒนามากกว่า 10,000 คนไม่ต้องใช้เวลาอ่านหัวข้อนี้เพียงอย่างเดียวโดยไม่คำนึงถึงผู้อื่นทั้งหมดที่ใช้เวลาในการเปรียบเทียบมากขึ้น
mmm

1
มีทางเดียวเท่านั้นที่จะทำให้อาร์เรย์ของคุณว่างเปล่าด้วยข้อมูลขาเข้าใหม่และทิ้งมันอีกครั้ง คนอื่น ๆ ทั้งหมดนั้นไม่ได้หรือกำลังหิวอย่างไร้ประสิทธิภาพและซีพียูที่ไม่อาจยกโทษได้ ทางเลือกเดียวที่ใช้งานได้จริงคือA(n) = A.splice( 0, A.length );ในกรณีที่คุณต้องการสำรองข้อมูลเนื้อหาก่อนหน้าของคุณ ps Array.lengthเป็นคุณสมบัติ \ วิธีอ่านเขียนในกรณีที่คุณพลาดข้อเท็จจริงพื้นฐานนั้นไป หมายความว่าคุณสามารถขยายความยาวใหม่คุณไม่สามารถตัดความยาวได้ตามที่คุณต้องการและในหมู่คนอื่น ๆ คุณสามารถยกเลิกสมาชิกทั้งหมดโดยการลดความยาวเป็น 0 มันคือมีดชาวสวิสของอาเรย์
Bekim Bacaj

63

การทดสอบประสิทธิภาพ:

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

9
การเพิ่มเปอร์เซ็นต์การเปลี่ยนแปลงนั้นไม่ได้ใช้งานมากนักโดยไม่สังเกตแพลตฟอร์มของคุณ ที่ป๊อปอัพเครื่องของฉันเร็วกว่า Chrome 34 แต่ช้ากว่า [] ใน Firefox ล่าสุด
สไตล์ของ Matt

2
การทดสอบใน Firefox 39.0 32 บิตบน Windows NT 6.3 64 บิต a = [] เร็วที่สุด!
Reza-S4

5
มีบางสิ่งที่แปลกประหลาดในผลการทดสอบนี้ภายใต้ Chrome วิธี popping loop จะอยู่ในนรกได้เร็วแค่ไหนแล้วอีก 3 โซลูชั่น?
chqrlie

9
@chqrlie มันไม่ใช่ มันเป็นวิธีที่ช้าที่สุด การทดสอบเกณฑ์มาตรฐานมีข้อบกพร่อง
Philippe Leybaert

15
โปรดลบคำตอบนี้เพราะมันผิดและเชื่อมโยงไปยังข้อบกพร่องที่ไม่มีความหมายเพื่อเป็นหลักฐานปลอม
James Wakefield

35

คุณสามารถเพิ่มสิ่งนี้ลงในไฟล์ JavaScript เพื่อให้อาร์เรย์ของคุณ "ล้างข้อมูล":

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

จากนั้นคุณสามารถใช้สิ่งนี้:

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

หรือถ้าคุณต้องการให้แน่ใจว่าคุณไม่ได้ทำลายบางสิ่ง:

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

ผู้คนจำนวนมากคิดว่าคุณไม่ควรแก้ไขวัตถุพื้นเมือง (เช่น Array) และฉันอยากเห็นด้วย โปรดใช้ความระมัดระวังในการตัดสินใจว่าจะจัดการกับสิ่งนี้อย่างไร


1
@naomik คุณช่วยอธิบายเหตุผลของคุณได้ไหมว่าทำไมการทำสิ่งนี้ถึงขมวดคิ้ว?
ไม่ได้กำหนด

17
มันเป็น "frowned เมื่อ" เพื่อแก้ไขฟังก์ชั่นดั้งเดิมจาวาสคริปต์เช่น Array และ String คุณอาจใช้งานฟังก์ชั่นที่มีอยู่แล้วมากเกินไปและทำลายคลาสอ็อบเจ็กต์ อาจมีเอ็นจิ้น javascript ที่คลุมเครือซึ่งชัดเจนแล้ว () และคาดว่ามันจะมีพฤติกรรมที่แตกต่างออกไป เหยียบอย่างระมัดระวังคือสิ่งที่ฉันพูด
ออกแบบโดย Adrian

ปัญหาเกี่ยวกับการทำ foreach กับสมาชิกของอาร์เรย์จะเริ่มต้นด้วยการรวมclearคีย์?
ErikE


19

มีความสับสนและข้อมูลที่ผิดมากมายในขณะที่ประสิทธิภาพของ pop / shift ทั้งในคำตอบและความคิดเห็น โซลูชัน while / pop มีประสิทธิภาพการทำงานที่แย่ที่สุดตามที่คาดไว้ สิ่งที่เกิดขึ้นจริงคือการตั้งค่าทำงานเพียงครั้งเดียวสำหรับแต่ละตัวอย่างที่เรียกใช้ข้อมูลโค้ดในการวนซ้ำ เช่น:

var arr = [];

for (var i = 0; i < 100; i++) { 
    arr.push(Math.random()); 
}

for (var j = 0; j < 1000; j++) {
    while (arr.length > 0) {
        arr.pop(); // this executes 100 times, not 100000
    }
}

ฉันได้สร้างการทดสอบใหม่ที่ทำงานอย่างถูกต้อง:

http://jsperf.com/empty-javascript-array-redux

คำเตือน:แม้ในการทดสอบเวอร์ชันนี้คุณจะไม่เห็นความแตกต่างที่แท้จริงเนื่องจากการโคลนอาร์เรย์จะใช้เวลาส่วนใหญ่ในการทดสอบ มันยังคงแสดงให้เห็นว่าspliceเป็นวิธีที่เร็วที่สุดในการล้างอาเรย์ (ไม่ต้องคำนึง[]ถึงเพราะในขณะที่มันเป็นฟอเรสต์ที่เร็วที่สุดก็ไม่ได้เป็นการล้างอาเรย์ที่มีอยู่จริงๆ)


จุดดีมาก! ฉันจะอัปเดตคำตอบดั้งเดิมด้วยผลลัพธ์การวัดประสิทธิภาพที่ถูกต้อง
Philippe Leybaert

ฉันไม่อยากจะเชื่อเลยว่าไม่มีใครพบข้อผิดพลาดของมาตรฐาน ด้วยจำนวนการดูมากกว่าครึ่งล้านครั้งคุณจะคาดหวังว่าจะมีใครเห็น Diadistis ที่ยอดเยี่ยมทำงาน
Philippe Leybaert

15

ในกรณีที่คุณสนใจในการจัดสรรหน่วยความจำคุณอาจเปรียบเทียบแต่ละวิธีโดยใช้บางอย่างเช่นjsfiddle นี้ร่วมกับแท็บเส้นเวลาของเครื่องมือ dev Chrome คุณจะต้องการใช้ไอคอนถังขยะที่ด้านล่างเพื่อบังคับให้มีการรวบรวมขยะหลังจาก 'ล้าง' อาร์เรย์ สิ่งนี้จะให้คำตอบที่ชัดเจนยิ่งขึ้นสำหรับเบราว์เซอร์ที่คุณเลือก คำตอบมากมายที่นี่แก่แล้วและฉันจะไม่พึ่งพาพวกเขา แต่ควรทดสอบเหมือนในคำตอบของ @ tanguy_k ด้านบน

(สำหรับคำนำของแท็บดังกล่าวข้างต้นคุณสามารถตรวจสอบที่นี่ )

Stackoverflow บังคับให้ฉันคัดลอก jsfiddle ดังนั้นนี่คือ:

<html>
<script>
var size = 1000*100
window.onload = function() {
  document.getElementById("quantifier").value = size
}

function scaffold()
{
  console.log("processing Scaffold...");
  a = new Array
}
function start()
{
  size = document.getElementById("quantifier").value
  console.log("Starting... quantifier is " + size);
  console.log("starting test")
  for (i=0; i<size; i++){
    a[i]="something"
  }
  console.log("done...")
}

function tearDown()
{
  console.log("processing teardown");
  a.length=0
}

</script>
<body>
    <span style="color:green;">Quantifier:</span>
    <input id="quantifier" style="color:green;" type="text"></input>
    <button onclick="scaffold()">Scaffold</button>
    <button onclick="start()">Start</button>
    <button onclick="tearDown()">Clean</button>
    <br/>
</body>
</html>

และคุณควรรับทราบว่ามันอาจขึ้นอยู่กับชนิดขององค์ประกอบอาร์เรย์เนื่องจาก javascript จัดการสตริงที่แตกต่างจากประเภทดั้งเดิมอื่น ๆ ไม่ต้องพูดถึงอาร์เรย์ของวัตถุ ประเภทอาจมีผลต่อสิ่งที่เกิดขึ้น


15

คุณสามารถสร้างฟังก์ชั่นที่จะทำเพื่อคุณเปลี่ยนความยาวหรือเพิ่มไปยังArray ดั้งเดิมได้อย่างง่ายดายremove()เพื่อใช้ซ้ำ

ลองนึกภาพคุณมีอาร์เรย์นี้:

var arr = [1, 2, 3, 4, 5]; //the array

ตกลงเพียงแค่เรียกใช้สิ่งนี้:

arr.length = 0; //change the length

และผลลัพธ์คือ:

[] //result

วิธีง่ายๆในการล้างอาเรย์ ...

ด้วยการใช้ loop ซึ่งไม่จำเป็น แต่เป็นอีกวิธีหนึ่งในการทำเช่นนั้น:

/* could be arr.pop() or arr.splice(0)
don't need to return as main array get changed */

function remove(arr) {
  while(arr.length) {
    arr.shift(); 
  }
}

นอกจากนี้ยังมีวิธีการที่ยุ่งยากซึ่งคุณสามารถนึกถึงตัวอย่างเช่นสิ่งนี้:

arr.splice(0, arr.length); //[]

ดังนั้นถ้า arr มี 5 รายการมันจะแบ่ง 5 รายการจาก 0 ซึ่งหมายความว่าไม่มีอะไรเหลืออยู่ในอาร์เรย์

นอกจากนี้ยังมีวิธีอื่น ๆ เช่นกำหนดค่าอาร์เรย์อีกครั้งเช่น

arr = []; //[]

หากคุณดูที่ฟังก์ชัน Array มีวิธีการอื่น ๆ อีกมากมาย แต่วิธีที่แนะนำมากที่สุดอาจเปลี่ยนความยาวได้

ดังที่ฉันได้กล่าวไว้ในตอนแรกคุณยังสามารถสร้างต้นแบบ remove () ตามที่มันเป็นคำตอบสำหรับคำถามของคุณ คุณสามารถเลือกหนึ่งในวิธีการด้านบนและสร้างต้นแบบให้กับวัตถุ Array ใน JavaScript ได้เช่น:

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

และคุณสามารถเรียกมันอย่างนี้เพื่อล้างอาเรย์ใด ๆ ในแอปพลิเคชันจาวาสคริปต์ของคุณ:

arr.remove(); //[]

arr.length = 0; // เปลี่ยนความยาว
Ajay Malhotra

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

และเรียกมันว่า: array.clear();


77
กรุณาอย่าสนับสนุนการปรับเปลี่ยนของวัตถุพื้นเมือง
ขอบคุณ

21
เหตุใดผู้คนจึงมีแนวโน้มที่จะคว้าคำตอบที่ได้รับการยอมรับและนำไปไว้ในฟังก์ชันต้นแบบ? คุณทำสิ่งนี้จริงในโครงการของคุณหรือไม่? คุณมีไลบรารี่ขนาดใหญ่ของการเพิ่มเติมต้นแบบที่คุณรวมไว้ในทุกโครงการหรือไม่?
nurettin

4
ทำไมไม่เพียงแค่พิมพ์ array.length = 0
ออกแบบโดย Adrian

10
@naomik "โปรดอย่าสนับสนุนการดัดแปลงของวัตถุดั้งเดิม" - ฉันเห็นด้วยกับสิ่งนี้อย่างสมบูรณ์ แต่เพียงแค่ทำซ้ำประโยคด้วยตัวเองเจอว่าหยิ่ง ใครบางคนที่เสนอวิธีการแก้ปัญหาดังกล่าวมีแนวโน้มที่จะไม่รับรู้ถึงผลที่ตามมาและทิ้งบรรทัดนี้ไว้แทนที่จะให้คำอธิบายสั้น ๆ หรือลิงก์ไม่ได้สื่อความหมายอื่นนอกจาก"เราคนฉลาดกว่าคุณบอกคุณว่าอย่าทำเช่นนี้ เพราะเรารู้ดีกว่า"
John Weisz


12

A.splice(0);

ฉันเพิ่งทำสิ่งนี้ในรหัสที่ฉันกำลังทำงานอยู่ มันล้างอาร์เรย์


ไม่มีคุณเพิ่งสลับคอนเทนเนอร์อาเรย์ที่มีชื่อกับที่ไม่ระบุชื่อที่เพิ่งสร้างใหม่ `var A = [1,2,3,4]; var B; B = A.splice (0); console.log (A); console.log (B); '
Bekim Bacaj

12

หากคุณกำลังใช้

a = []; 

จากนั้นคุณจะกำหนดการอ้างอิงอาเรย์ใหม่ให้กับหากการอ้างอิงใน a ถูกกำหนดให้กับตัวแปรอื่น ๆ แล้วมันจะไม่ว่างเปล่าที่อาเรย์นั้นด้วยและด้วยเหตุนี้ตัวรวบรวมขยะจะไม่รวบรวมหน่วยความจำนั้น

สำหรับอดีต

var a=[1,2,3];
var b=a;
a=[];
console.log(b);// It will print [1,2,3];

หรือ

a.length = 0;

เมื่อเราระบุa.lengthเราเพียงรีเซ็ตขอบเขตของอาเรย์และหน่วยความจำสำหรับองค์ประกอบอาเรย์ส่วนที่เหลือจะถูกเชื่อมต่อโดยตัวรวบรวมขยะ

แทนที่จะแก้ปัญหาทั้งสองนี้ดีกว่า

a.splice(0,a.length)

และ

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

ตามคำตอบก่อนหน้าโดย kenshou.html วิธีที่สองนั้นเร็วกว่า


10
นอกเหนือจากการทำผิดa.lengthฉันไม่เห็นสิ่งที่คำตอบใหม่นี้เพิ่มไปยังเธรด?
Bergi

@Bergi ฉันแค่ต้องการที่จะมุ่งเน้นเกี่ยวกับการเป็นตัวแทนของหน่วยความจำจริงเกี่ยวกับอาเรย์
Laxmikant Dange

คุณมีแหล่งข้อมูลใดบ้างเพื่อยืนยันเอ็นจิน JS ที่จะสร้างอาร์เรย์ใหม่เมื่อa.length=0;ดำเนินการ? เครื่องยนต์เหล่านั้นทำหน้าที่อย่างไรa.length=500;และa.length=4;?
joeytwiddle

ฉันลองในเบราว์เซอร์ส่วนใหญ่เช่น IE, Firefox, Chrome มันกำลังสร้างอาร์เรย์ใหม่ หากคุณตั้งความยาวมากกว่า 0 มันจะสร้างอาร์เรย์ที่มีองค์ประกอบที่ไม่ได้กำหนดนั่นคือมันจะเก็บตำแหน่งหน่วยความจำบางส่วนไว้เท่านั้น
Laxmikant Dange

1
var a = [1]; var b = a; a.length = 0; console.log(b)พิมพ์ออกArray [ ]มาดังนั้นมันไม่เหมือนว่าจะสร้างอาร์เรย์ใหม่ให้ฉัน
John Montgomery

9

ใช้คำแนะนำเบื้องต้นของJan ที่แก้ไขแล้ว:

var originalLength = A.length;
for (var i = originalLength; i > 0; i--) {
     A.pop();
}

12
ทำไมคุณต้องการทำสิ่งนี้ เหตุใดจึงต้องเพิ่มตัวแปรอีกสองตัวและรหัสเพิ่มเติมเพื่อทำสิ่งเดียวกัน
Killah

6

หากคุณใช้ค่าคงที่คุณจะไม่มีทางเลือก:

const numbers = [1, 2, 3]

คุณไม่สามารถกำหนดใหม่:

numbers = []

คุณสามารถตัดทอน:

numbers.length = 0

5

ป้อนคำอธิบายรูปภาพที่นี่

หากต้องการล้างตำแหน่งหน่วยความจำปัจจุบันของอาร์เรย์ให้ใช้: 'myArray.length = 0'หรือ'myArray.pop() UN-till its length is 0'

  • length: คุณสามารถตั้งค่าคุณสมบัติความยาวเป็นตัดทอนอาร์เรย์ได้ตลอดเวลา เมื่อคุณขยายอาร์เรย์โดยเปลี่ยนคุณสมบัติความยาวจำนวนองค์ประกอบที่แท้จริงจะเพิ่มขึ้น
  • pop() : เมธอด pop ลบองค์ประกอบสุดท้ายออกจากอาร์เรย์และส่งคืนค่าที่คืนค่าที่ถูกลบออก
  • shift(): วิธีการเลื่อนจะลบองค์ประกอบที่ดัชนี zeroethและเลื่อนค่าที่ดัชนีต่อเนื่องกันลงจากนั้นส่งคืนค่าที่ถูกลบออก

ตัวอย่าง:

var arr = ['77'];
arr.length = 20;
console.log("Increasing : ", arr); // (20) ["77", empty × 19]
arr.length = 12;
console.log("Truncating : ", arr); // (12) ["77", empty × 11]

var mainArr = new Array();
mainArr = ['1', '2', '3', '4'];

var refArr = mainArr;
console.log('Current', mainArr, 'Refered', refArr);

refArr.length = 3;
console.log('Length: ~ Current', mainArr, 'Refered', refArr);

mainArr.push('0');
console.log('Push to the End of Current Array Memory Location \n~ Current', mainArr, 'Refered', refArr);

mainArr.poptill_length(0);
console.log('Empty Array \n~ Current', mainArr, 'Refered', refArr);

Array.prototype.poptill_length = function (e) {
  while (this.length) {
    if( this.length == e ) break;

    console.log('removed last element:', this.pop());
  }
};

  • new Array() | [] สร้างอาร์เรย์ที่มีหน่วยความจำตำแหน่งใหม่โดยใช้หรือArray constructorarray literal

    mainArr = []; // a new empty array is addressed to mainArr.
    
    var arr = new Array('10'); // Array constructor
    arr.unshift('1'); // add to the front
    arr.push('15'); // add to the end
    console.log("After Adding : ", arr); // ["1", "10", "15"]
    
    arr.pop(); // remove from the end
    arr.shift(); // remove from the front
    console.log("After Removing : ", arr); // ["10"]
    
    var arrLit = ['14', '17'];
    console.log("array literal « ", indexedItem( arrLit ) ); // {0,14}{1,17}
    
    function indexedItem( arr ) {
        var indexedStr = "";
        arr.forEach(function(item, index, array) {
            indexedStr += "{"+index+","+item+"}";
            console.log(item, index);
        });
        return indexedStr;
    }
  • slice() : โดยการใช้ฟังก์ชั่น slice เราจะได้รับสำเนาขององค์ประกอบตื้น ๆ จากอาร์เรย์เดิมพร้อมที่อยู่หน่วยความจำใหม่ดังนั้นการแก้ไขใด ๆ บน cloneArr จะไม่ส่งผลกระทบต่ออาร์เรย์ | ดั้งเดิม

    var shallowCopy = mainArr.slice(); // this is how to make a copy
    
    var cloneArr = mainArr.slice(0, 3); 
    console.log('Main', mainArr, '\tCloned', cloneArr);
    
    cloneArr.length = 0; // Clears current memory location of an array.
    console.log('Main', mainArr, '\tCloned', cloneArr);

"ความยาว: ปรากฏจนถึงความยาวของอาร์เรย์เป็นขนาดที่ระบุ" ใครบอกเรื่องไร้สาระนี้กับคุณ
Bekim Bacaj

@BekimBacaj ในสาระสำคัญมันจะมีผลเช่นเดียวกัน มันอาจจะควรจะพูดแทนเพียงlength = ? length
Tuupertunut

@BekimBacaj ฉันได้อัปเดตคำตอบของฉันฉันแค่คิดว่าความยาวจะปรากฏขึ้นจนถึงความยาว แต่ฉันแก้ไขตอนนี้ความยาวนั้นก็แค่ตัดหรือเพิ่มขนาดของอาร์เรย์
Yash

3

ฉันประหลาดใจที่ยังไม่มีใครแนะนำสิ่งนี้:

let xs = [1,2,3,4];
for (let i in xs)
    delete xs[i];

สิ่งนี้ทำให้เกิดอาร์เรย์ในสถานะที่ค่อนข้างแตกต่างจากโซลูชันอื่น ในความหมายอาร์เรย์ได้ถูก 'ว่าง':

xs
=> Array [ <4 empty slots> ]

[...xs]
=> Array [ undefined, undefined, undefined, undefined ]

xs.length
=> 4

xs[0]
=> ReferenceError: reference to undefined property xs[0]

คุณสามารถสร้างอาร์เรย์ที่เทียบเท่าได้ด้วย[,,,,]หรือArray(4)


7
อาจเป็นคำตอบที่ดีสำหรับคำถามอื่น: "วิธีแปลงองค์ประกอบทั้งหมดในอาร์เรย์เป็นองค์ประกอบที่ไม่ได้กำหนด"
รูเบน

แม้ว่าภายในจะมีความแตกต่างระหว่างองค์ประกอบที่ไม่ได้กำหนดและช่องว่าง ("หลุม")
Cauterite

-9

ใช้ด้านล่างหากคุณต้องการล้าง Angular 2+ FormArray

public emptyFormArray(formArray:FormArray) {
    for (let i = formArray.controls.length - 1; i >= 0; i--) {
        formArray.removeAt(i);
    }
}

10
สิ่งนี้ไม่เกี่ยวข้องและไม่ใช่แม้แต่ JavaScript
Emile Bergeron
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.