ผลักดันองค์ประกอบหลายรายการเพื่ออาร์เรย์


284

ฉันพยายามที่จะผลักองค์ประกอบหลายรายการเป็นหนึ่งอาร์เรย์ แต่ได้รับข้อผิดพลาด

> a = []
[]
> a.push.apply(null, [1,2])
TypeError: Array.prototype.push called on null or undefined

ฉันพยายามทำสิ่งที่คล้ายกันที่ฉันทำในทับทิมฉันคิดว่าapplyมันเป็นอย่าง*นั้น

>> a = []
=> []
>> a.push(*[1,2])
=> [1, 2]

คำตอบ:


240

เมื่อใช้ฟังก์ชั่นมากที่สุดของวัตถุที่มีapplyหรือcallที่contextพารามิเตอร์ต้องเป็นวัตถุที่คุณกำลังทำงานอยู่

ในกรณีนี้คุณต้องการa.push.apply(a, [1,2])(หรือมากกว่านั้นถูกต้องArray.prototype.push.apply(a, [1,2]))


618

คุณสามารถผลักองค์ประกอบหลาย ๆ ชิ้นเข้าไปในอาร์เรย์ได้ด้วยวิธีการดังต่อไปนี้

var a = [];
    
a.push(1, 2, 3);

console.log(a);


1
คำตอบนี้และคำตอบที่เลือกจะให้ผลลัพธ์ที่แตกต่างกันและอาจไม่คาดคิด a.push (1) กับ a.push ([1])
oevna

1
ใครสามารถอธิบายได้ว่าทำไมจึงมีคะแนนมากกว่าคำตอบที่ยอมรับ? มันอาจจะง่ายกว่า แต่มีความยืดหยุ่นน้อยกว่า ถ้าคุณต้องการผสาน 2 อาร์เรย์สิ่งนี้จะไม่ทำงาน
สีฟ้า

@BluE ถ้าคุณต้องการรวมสองอาร์เรย์เพียงใช้ array.concat ()
Florent Arlandis

@FlorentArlandis array.concat ไม่ทำงานเพื่อเพิ่มอาร์เรย์ที่ 2 ในรายการแรก มันจะสร้างขึ้นมาใหม่ ฉันรู้ว่ามันคล้ายกัน ผู้ดำเนินการแพร่กระจายคือสิ่งที่ฉันกำลังมองหา เพียงแค่ดูคำตอบและความคิดเห็นอื่น ๆ ที่มีเพื่อดูรายละเอียด
BluE

435

ขณะนี้อยู่ใน ECMAScript2015 (aka ES6) คุณสามารถใช้ตัวดำเนินการสเปรดเพื่อผนวกหลายรายการพร้อมกัน:

var arr = [1];
var newItems = [2, 3];
arr.push(...newItems);
console.log(arr);

ดูตารางความเข้ากันได้ ES6 ของ Kangaxเพื่อดูว่าเบราว์เซอร์ใดบ้างที่เข้ากันได้


41
whaaaaaaat สิ่งนี้ยอดเยี่ยมมากบวกถ้าคุณทำด้วย typescript มันจะคอมไพล์เพื่อ push.apply ดังนั้นคุณจึงมีความเข้ากันได้ย้อนหลัง
Chris

72

คุณสามารถใช้Array.concat:

var result = a.concat(b);

16
Array.prototype.concat ส่งคืนอาร์เรย์ใหม่
suricactus

12
เขาต้องการที่จะผลักดันอาร์เรย์ที่มีอยู่แล้วดังนั้นจึงArray.prototype.push.apply(arr1, arr2)เป็นคำตอบที่ถูกต้องเพราะการใช้งานarr1.concat(arr2)คุณกำลังสร้างอาร์เรย์ใหม่
suricactus

3
@uricactus arr1 = arr1.concat(arr2)ไม่ใช่เรื่องใหญ่และดูสะอาดกว่ามาก การเปลี่ยนเป็นอาเรย์เก่าหรือการแทนที่อาเรย์เก่าด้วยสิ่งใหม่นั้นขึ้นอยู่กับความต้องการของคุณ หากคุณจัดการกับองค์ประกอบ 10m + ที่ผลักไปยังอาเรย์เก่าจะทำงานได้เร็วขึ้นหากคุณจัดการชิ้นเล็ก ๆ คุณจะไม่พบความแตกต่างของความเร็ว ตัวเลือกทั้งสองอย่างถูกต้องสมบูรณ์
VisioN

5
@YuvalA prototype.push.applyโทรpushครั้งเดียวเท่านั้น และความแตกต่างดังกล่าวไม่จำเป็นต้องเกี่ยวกับความเร็ว แต่เป็นการดำเนินการในสถานที่เทียบกับการสร้างอาร์เรย์ใหม่ ถ้าฉันมีวิธีการที่ใช้อาร์เรย์และควรจะแก้ไขมันในสถานที่? concatวิธีการไม่อาจทำงานได้แม้จะมีรหัส VisionN ของมันจะไม่ปรับเปลี่ยนตัวแปรสำหรับการโทรของฟังก์ชัน
coderforlife

1
a = a.concat(b)ยังคงเป็นไวยากรณ์ที่สั้นกว่าArray.prototype.push.apply(arr1, arr2)
Aizzat Suhardi

22

หากคุณต้องการทางเลือกArray.concatใน ECMAScript 2015 (aka ES6, ES2015) ที่ชอบไม่ได้ปรับเปลี่ยนอาร์เรย์ แต่ส่งกลับอาร์เรย์ใหม่ที่คุณสามารถใช้ตัวดำเนินการแพร่กระจายเช่น:

var arr = [1];
var newItems = [2, 3];
var newerItems = [4, 5];
var newArr = [...arr, ...newItems, ...newerItems];
console.log(newArr);

โปรดทราบว่านี่จะแตกต่างจากpushวิธีการเป็นpushวิธีการกลายพันธุ์ / ปรับเปลี่ยนอาร์เรย์

หากคุณต้องการที่จะดูว่าบาง ES2015 คุณสมบัติการทำงานในเบราว์เซอร์ของคุณตรวจสอบตารางการทำงานร่วมกันของ Kangax

คุณสามารถใช้Babelหรือ transpiler ที่คล้ายกันได้หากคุณไม่ต้องการรอการสนับสนุนเบราว์เซอร์และต้องการใช้ ES2015 ในการผลิต


4

Array.prototype.push(a, b)มีคำตอบจำนวนมากแนะนำให้ใช้งาน: มันเป็นวิธีที่ดีแต่ถ้าคุณจะมีขนาดใหญ่มาก b คุณจะมีข้อผิดพลาดสแต็คล้น (เพราะ args มากเกินไป) ระวังที่นี่

ดูวิธีที่มีประสิทธิภาพมากที่สุดในการเชื่อมต่ออาร์เรย์ N คืออะไร? สำหรับรายละเอียดเพิ่มเติม


3
สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม หากต้องการวิจารณ์หรือขอคำชี้แจงจากผู้แต่งโปรดแสดงความคิดเห็นใต้โพสต์ของพวกเขา [ฉันจะเขียนคำตอบที่ดีได้อย่างไร? ] ( stackoverflow.com/help/how-to-answer )
mrun

1
ขออภัยฉันไม่สามารถแสดงความคิดเห็นภายใต้คำตอบ (ยกเว้นของตัวเอง) เพราะชื่อเสียงไม่เพียงพอ :) แต่ดูเหมือนว่านี่ควรจะกล่าวถึงที่นี่เพื่อให้มีภาพรวมที่สมบูรณ์ คุณช่วยทำมันให้ฉันได้ไหม จากนั้นฉันจะลบคำตอบของฉัน
12kb

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