วิธีการเริ่มต้นความยาวของอาเรย์ใน JavaScript?


542

บทเรียนส่วนใหญ่ที่ฉันได้อ่านในอาร์เรย์ใน JavaScript (รวมถึงw3schoolsและdevguru ) แนะนำว่าคุณสามารถเริ่มต้นอาร์เรย์ด้วยความยาวที่แน่นอนโดยส่งจำนวนเต็มไปยังตัวสร้าง Array โดยใช้var test = new Array(4);ไวยากรณ์

หลังจากใช้ซินแท็กซ์นี้อย่างอิสระในไฟล์ js ของฉันฉันรันหนึ่งในไฟล์ผ่านjsLintและทำให้เป็นอิสระ:

ข้อผิดพลาด: ปัญหาที่บรรทัด 1 อักขระ 22: คาดว่า ')' และเห็น '4' แทน
var test = อาร์เรย์ใหม่ (4);
ปัญหาที่บรรทัดที่ 1 อักขระ 23: คาดหวัง ';' และแทนที่จะเห็น ')'
var test = อาร์เรย์ใหม่ (4);
ปัญหาที่บรรทัดที่ 1 อักขระ 23: ต้องการตัวระบุและแทนที่จะเห็น ')'

หลังจากอ่านคำอธิบายของ jsLint เกี่ยวกับพฤติกรรมของมันดูเหมือนว่า jsLint ไม่ชอบnew Array()ไวยากรณ์และชอบ[]เมื่อประกาศอาร์เรย์

ดังนั้นฉันมีคำถามสองสามข้อ:

ก่อนอื่นทำไม ฉันใช้ความเสี่ยงใด ๆ โดยใช้new Array()ไวยากรณ์แทนหรือไม่ เบราว์เซอร์ที่ฉันควรทราบมีความเข้ากันไม่ได้หรือไม่

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

var test = [];
test.length = 4;

js มาตรฐานนอกจากนี้ยังให้คำแนะนำ กับการใช้new Array()ในทั่วไป แต่ก็โอเคที่มีขนาดที่ระบุ ฉันคิดว่ามันสอดคล้องกับบริบทของโค้ดทั้งหมด
cregox

สำหรับผู้ที่ต้องการ preallocate โครงสร้างอาร์เรย์เข้มงวดมากขึ้นมีประเภทอาร์เรย์ โปรดทราบว่าประโยชน์ด้านประสิทธิภาพอาจแตกต่างกันไป
rovyko

คำตอบ:


398
  1. ทำไมคุณต้องการเริ่มต้นความยาว? ในทางทฤษฎีไม่มีความจำเป็นในเรื่องนี้ มันยังสามารถส่งผลให้เกิดพฤติกรรมที่ทำให้เกิดความสับสนเพราะการทดสอบทั้งหมดที่ใช้lengthเพื่อหาว่าอาร์เรย์ว่างเปล่าหรือไม่จะรายงานว่าอาร์เรย์ไม่ว่างเปล่า การทดสอบ
    บางอย่าง แสดงให้เห็นว่าการตั้งค่าความยาวเริ่มต้นของอาร์เรย์ขนาดใหญ่อาจมีประสิทธิภาพมากขึ้นถ้าอาร์เรย์เต็มหลังจากนั้น แต่ประสิทธิภาพที่เพิ่มขึ้น (ถ้ามี) ดูเหมือนจะแตกต่างจากเบราว์เซอร์ไปยังเบราว์เซอร์

  2. jsLint ไม่ชอบnew Array()เพราะตัวสร้างมีความกำกวม

    new Array(4);

    สร้างอาร์เรย์ความยาวที่ว่างเปล่า4 แต่

    new Array('4');

    สร้างอาร์เรย์ที่มีค่า '4'

เกี่ยวกับความคิดเห็นของคุณ: ใน JS คุณไม่จำเป็นต้องเริ่มต้นความยาวของอาร์เรย์ มันเติบโตแบบไดนามิก คุณสามารถเก็บความยาวในตัวแปรบางตัวได้เช่น

var data = [];
var length = 5; // user defined length

for(var i = 0; i < length; i++) {
    data.push(createSomeObject());
}

13
จำนวนวัตถุในอาร์เรย์นั้นเป็นแบบที่ผู้ใช้กำหนดดังนั้นฉันจึงให้ผู้ใช้เลือกตัวเลขจากนั้นจึงเริ่มต้นอาร์เรย์ด้วยช่องจำนวนมาก จากนั้นฉันเรียกใช้forลูปที่วนซ้ำตามความยาวของอาเรย์และเติมเต็ม ฉันเดาว่าจะมีวิธีอื่นในการทำเช่นนี้ใน JavaScript ดังนั้นคำตอบที่แท้จริงของ "ทำไมฉันถึงต้องการทำเช่นนี้" คือ "เพราะนิสัยเก่า ๆ ที่เกิดขึ้นในขณะที่เขียนโปรแกรมในภาษาอื่น" :)
Michael Martin-Smucker

4
@mlms เพียงแค่ปล่อยให้วนซ้ำวนซ้ำตามจำนวนที่ผู้ใช้กำหนดแทนที่จะต้องตั้งค่าความยาวอาร์เรย์แล้ววนซ้ำไปเรื่อย ๆ นั่นไม่สมเหตุสมผลสำหรับคุณหรือ
Šime Vidas

151
<blockquote> ทำไมคุณต้องการเริ่มต้นความยาว ในทางทฤษฎีไม่มีความจำเป็นในเรื่องนี้ และการทดสอบทั้งหมดที่ใช้ความยาวเพื่อค้นหาว่าอาเรย์นั้นว่างเปล่าหรือไม่จะล้มเหลว </blockquote> อืมอาจจะมีประสิทธิภาพหรือไม่ การตั้งค่าองค์ประกอบที่มีอยู่ล่วงหน้าของอาเรย์นั้นเร็วกว่าการเพิ่มองค์ประกอบนั้นทันที
codehead

45
"เวลาเลิกนิสัยการเขียนโปรแกรมเก่า" ความคิดเห็นนั้นไม่จำเป็นจริงๆ ภาษาที่มีโครงสร้างที่เหมาะสมจะมีประสิทธิภาพเหนือกว่า ecmascript mombo jambo
user151496

10
@ codehead: ตามคำพูดนี้: "การตั้งค่าองค์ประกอบที่มีอยู่ล่วงหน้าของอาเรย์นั้นเร็วกว่าการเพิ่มองค์ประกอบนั้นในทันที": โปรดทราบว่าnew Array(10)จะไม่สร้างอาร์เรย์ที่มี 10 องค์ประกอบที่ไม่ได้กำหนด มันสร้างอาร์เรย์ว่างเปล่าที่มีความยาว 10 ดูคำตอบสำหรับความจริงที่น่ารังเกียจนี้: stackoverflow.com/questions/18947892//
Milimetric

598
  • Array(5) ให้อาร์เรย์ที่มีความยาว 5 แต่ไม่มีค่าดังนั้นคุณจึงไม่สามารถทำซ้ำได้

  • Array.apply(null, Array(5)).map(function () {}) ให้อาร์เรย์ที่มีความยาว 5 และไม่ได้กำหนดเป็นค่าตอนนี้สามารถวนซ้ำได้

  • Array.apply(null, Array(5)).map(function (x, i) { return i; }) ให้อาร์เรย์ที่มีความยาว 5 และค่า 0,1,2,3,4

  • Array(5).forEach(alert)ไม่ทำอะไรเลยArray.apply(null, Array(5)).forEach(alert)ให้การแจ้งเตือน 5 ครั้ง

  • ES6ให้เราArray.fromดังนั้นตอนนี้คุณสามารถใช้Array.from(Array(5)).forEach(alert)

  • หากคุณต้องการที่จะเริ่มต้นกับค่าบางอย่างเหล่านี้เป็นที่ดีที่จะรู้ว่า ...
    Array.from('abcde'), Array.from('x'.repeat(5))
    หรือArray.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]


11
นี่คือสิ่งที่ฉันกำลังมองหา ฉันต้องการที่จะใช้แผนที่เป็นลำดับตรรกะ; สิ่งนี้ควรทำ ขอบคุณ!
jedd.ahyoung

3
ทำไม Array.apply () ให้ค่าที่ไม่ได้กำหนดเป็นค่า?
wdanxna

5
@wdanxna เมื่อArrayได้รับการขัดแย้งหลายครั้งมันวนซ้ำกับargumentsวัตถุและนำค่าแต่ละค่าไปใช้กับอาร์เรย์ใหม่อย่างชัดเจน เมื่อคุณเรียกArray.applyใช้อาเรย์หรือวัตถุที่มีคุณสมบัติความยาวArrayจะใช้ความยาวในการตั้งค่าแต่ละค่าของอาเรย์ใหม่อย่างชัดเจน นี่คือเหตุผลที่Array(5)ทำให้มีอาร์เรย์ 5 elisions ในขณะที่Array.apply(null, Array(5))ให้อาร์เรย์ของ 5 undefined สำหรับข้อมูลเพิ่มเติมโปรดดูที่นี้คำตอบ
KylePlusPlus

2
Array (5) กับ Array ใหม่ (5) แตกต่างกันหรือไม่?
Petr Hurtak

2
ยังสามารถเขียนเป็นArray.apply(null, Array(5)) Array.apply(null, {length: 5})มีไม่แตกต่างกันมาก แต่หลังมีความชัดเจนอย่างชัดเจนว่าเจตนาคือการสร้างอาร์เรย์ของlength 5และไม่ใช่อาร์เรย์ที่มี5
AlexMorley-Finch

271

ด้วยES2015.fill()ตอนนี้คุณสามารถทำได้:

// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)

ซึ่งมีความรัดกุมมากกว่านี้มาก Array.apply(0, new Array(n)).map(i => value)

มันเป็นไปได้ที่จะวาง0ในและเรียกใช้โดยไม่ขัดแย้งซึ่งจะเติมอาร์เรย์ที่มี.fill() undefined( อย่างไรก็ตามสิ่งนี้จะล้มเหลวใน typescript )


1
@AralRoca คุณก็สามารถใช้Polyfillให้บริการในหน้า MDN หรือพิจารณาใช้Modernizr
AP

4
ใช่โปรดลองก่อนแสดงความคิดเห็น
AP

1
@GarretWilson และ @Christian มันในสเปค When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
AP

1
@AP. ศูนย์มีการซ้ำซ้อน ทำArray(n).fill()
Pacerier

2
@Pierier ฉันไม่คิดว่า 0 ซ้ำซ้อน ตามนิยามประเภท es6 นี่คือลายเซ็นของฟังก์ชั่น: เติม (ค่า: T, เริ่มต้น?: หมายเลข, สิ้นสุด?: หมายเลข): ​​สิ่งนี้; ดังนั้นค่าการเติมจึงไม่เป็นตัวเลือก การรวบรวม typescript จะล้มเหลวในขณะที่การเรียกใช้ฟังก์ชันเขียนไว้ด้านบน
Micha Schwab

150
[...Array(6)].map(x => 0);
// [0, 0, 0, 0, 0, 0]

หรือ

Array(6).fill(0);
// [0, 0, 0, 0, 0, 0]

หมายเหตุ: คุณไม่สามารถวนซ้ำช่องว่างเช่น Array(4).forEach(() => …)


หรือ

( ปลอดภัยสำหรับตัวพิมพ์ดีด )

Array(6).fill(null).map((_, i) => i);
// [0, 1, 2, 3, 4, 5]

หรือ

วิธีคลาสสิกโดยใช้ฟังก์ชั่น (ทำงานในเบราว์เซอร์ใด ๆ )

function NewArray(size) {
    var x = [];
    for (var i = 0; i < size; ++i) {
        x[i] = i;
        return x;
    }
}

var a = NewArray(10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

สร้างอาร์เรย์ที่ซ้อนกัน

เมื่อสร้างอาเรย์แบบ 2 มิติด้วยการfillสังหรณ์ใจควรสร้างอินสแตนซ์ใหม่ แต่สิ่งที่เกิดขึ้นจริงคืออาร์เรย์เดียวกันจะถูกเก็บไว้เป็นข้อมูลอ้างอิง

var a = Array(3).fill([6]);
// [  [6], [6], [6]  ]

a[0].push(9);
// [  [6, 9], [6, 9], [6, 9]  ]

สารละลาย

var a = [...Array(3)].map(x => []);

a[0].push(4, 2);
// [  [4, 2], [], []  ]

ดังนั้น 3x2 Array จะมีหน้าตาดังนี้:

[...Array(3)].map(x => Array(2).fill(0));
// [  [0, 0], [0, 0], [0, 0]  ]

อาร์เรย์ N-Dim

function NArray(...dimensions) {
    var index = 0;
    function NArrayRec(dims) {
        var first = dims[0], next = dims.slice().splice(1); 
        if(dims.length > 1) 
            return Array(dims[0]).fill(null).map((x, i) => NArrayRec(next ));
        return Array(dims[0]).fill(null).map((x, i) => (index++));
    }
    return NArrayRec(dimensions);
}

var arr = NArray(3, 2, 4);
// [   [  [ 0,  1,  2,  3 ] , [  4,  5,  6,  7]  ],
//     [  [ 8,  9,  10, 11] , [ 12, 13, 14, 15]  ],
//     [  [ 16, 17, 18, 19] , [ 20, 21, 22, 23]  ]   ]

เริ่มต้นกระดานหมากรุก

var Chessboard = [...Array(8)].map((x, j) => {
    return Array(8).fill(null).map((y, i) => {
        return `${String.fromCharCode(65 + i)}${8 - j}`;
    });
});

// [ [A8, B8, C8, D8, E8, F8, G8, H8],
//   [A7, B7, C7, D7, E7, F7, G7, H7],
//   [A6, B6, C6, D6, E6, F6, G6, H6],
//   [A5, B5, C5, D5, E5, F5, G5, H5],
//   [A4, B4, C4, D4, E4, F4, G4, H4],
//   [A3, B3, C3, D3, E3, F3, G3, H3],
//   [A2, B2, C2, D2, E2, F2, G2, H2],
//   [A1, B1, C1, D1, E1, F1, G1, H1] ]

1
a[0].push(9); // [ [6, 9], [6], [6] ] ควรเป็น a[0].push(9); // [ [6, 9], [6, 9], [6, 9] ] เพราะแต่ละอาร์เรย์ซ้อนกันจะถูกเก็บไว้เป็นข้อมูลอ้างอิงดังนั้นการกลายพันธุ์หนึ่งอาร์เรย์มีผลต่อส่วนที่เหลือ คุณอาจพิมพ์เดียวกับมัน แต่ผมคิดว่า :)
Alex_Zhong

@Alex_Zhong ตรุว่าขอบคุณที่หายไปในการแก้ไข
Vlad

68

ที่สั้นที่สุด:

[...Array(1000)]

10
เพิ่มขึ้น แต่หนึ่ง caveat คุณไม่ควรเริ่มต้นบรรทัดใน JS ด้วยการ[ไม่ใช้;เพราะจะพยายามอ้างอิงบรรทัดข้างต้น ดังนั้นวิธีที่ปลอดภัยในการใช้บรรทัดนี้ซึ่งคาดการณ์ได้ในส่วนใด ๆ ของรหัสคือ:;[...Array(1000)]//.whateverOpsNeeded()
AP

ไม่ได้จริงๆ ลองใช้เครื่องมือสำหรับนักพัฒนา [...Array(5)].map((item, index) => ({ index })) ลองสิ่งนี้ด้วย:[...Array(5)]; console.log('hello');
Michael Mammoliti

2
ลองใช้ในไฟล์ js แบบหลายบรรทัด ถ้าบรรทัดแรกของคุณคือและบรรทัดถัดไปconst a = 'a' [...Array(5)].//irreleventคุณคิดว่าบรรทัดแรกจะแก้ปัญหาอะไร มันจะเป็นconst a = 'a'[...Array(5)]สิ่งที่จะส่งผลใน:Uncaught SyntaxError: Unexpected token ...
AP

7
ที่จริง แต่ในกรณีนี้ฉันจะบอกว่าปัญหาอยู่ที่อื่นอัฒภาคและผ้าสำลีมีความสำคัญในปัจจุบัน
Michael Mammoliti

8
@AP ตัวอย่างนั้นเป็นเหตุผลว่าทำไมคู่มือสไตล์จำนวนมากจึงลงท้ายด้วยทุกเซมิโคลอน const a = 'a'จะเป็นข้อผิดพลาด Lint ในกรณีนั้น อย่างไรก็ตามมันไม่มีอะไรเกี่ยวข้องกับคำตอบนี้
graup

41

ES6 แนะนำArray.fromซึ่งช่วยให้คุณสร้างวัตถุArrayจาก"อาร์เรย์เหมือน"หรือวัตถุiterablesใด ๆ :

Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ในกรณีนี้{length: 10}หมายถึงคำจำกัดความที่น้อยที่สุดของวัตถุ"คล้ายอาร์เรย์" : วัตถุว่างเปล่าที่มีเพียงlengthคุณสมบัติที่กำหนด

Array.from อนุญาตให้มีอาร์กิวเมนต์ที่สองเพื่อแมปผ่านอาร์เรย์ผลลัพธ์


2
@dain ฉันคิดว่า [... Array (10)] ดีกว่าstackoverflow.com/a/47929322/4137472
Alexander Shutau

1
ทำไมถึงดีกว่า การใช้ตัวสร้าง Array ไม่สนับสนุนและผู้ให้
ยืม

26

สิ่งนี้จะเริ่มต้นคุณสมบัติความยาวเป็น 4:

var x = [,,,,];

3
นั่นฉลาด มันไม่มีความยืดหยุ่นของนวกรรมิกเพราะคุณไม่สามารถใช้ตัวแปรเพื่อกำหนดความยาวได้ แต่มันจะตอบคำถามของฉันเมื่อฉันเริ่มใช้มันดังนั้น +1
Michael Martin-Smucker

12
ลองนึกภาพดูสิว่าสำหรับ 300 ไอเท็มเมื่อการแสดงเป็นเรื่องสำคัญ!
Marco Luglio

9
มีประสิทธิภาพเพิ่มขึ้นอย่างไม่น่าจะเป็นไปได้มากนักเมื่อทำการจัดสรรอาร์เรย์ล่วงหน้าด้วยขนาดที่เล็ก ความแตกต่างของประสิทธิภาพจะรับรู้ได้ดีขึ้นเมื่อสร้างอาร์เรย์ที่ใหญ่ขึ้น และในกรณีเหล่านั้นเริ่มต้นพวกเขาด้วยเครื่องหมายจุลภาคจะล้นหลามเล็กน้อย
Marco Luglio

6
ฉันคิดว่าสิ่งนี้จะให้ผลลัพธ์ที่แตกต่างกันในเบราว์เซอร์ที่แตกต่างกันเนื่องจากจุลภาคสุดท้ายบางครั้ง 4 และบางครั้ง 5 ดูstackoverflow.com/questions/7246618//
jperelli

1
แล้วไงvar size = 42; var myArray = eval("["+",".repeat(size)+"]");ล่ะ (ไม่ร้ายแรงขนาดนั้น)
xoxox

15

ฉันประหลาดใจที่ยังไม่มีวิธีแก้ปัญหาการทำงานที่แนะนำให้คุณกำหนดความยาวในหนึ่งบรรทัด ต่อไปนี้เป็นไปตาม UnderscoreJS:

var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);

ด้วยเหตุผลดังกล่าวข้างต้นฉันจะหลีกเลี่ยงการทำเช่นนี้เว้นแต่ว่าฉันต้องการเริ่มต้นอาร์เรย์เป็นค่าเฉพาะ เป็นที่น่าสนใจที่จะทราบว่ามีห้องสมุดอื่น ๆ ที่ใช้ช่วง ได้แก่ Lo-dash และ Lazy ซึ่งอาจมีลักษณะการทำงานที่แตกต่างกัน


ไม่จำเป็นต้องใช้เวทย์มนต์ขีดล่างที่นี่ การพึ่งพาเป็นเหมือนน้ำตาลมันดูหวานตั้งแต่แรก แต่ก่อนที่คุณจะรู้ว่าคุณเป็นโรคเบาหวาน
Romain Vincent

9

คนโปรดอย่ายอมแพ้นิสัยเก่าของคุณ มีความแตกต่างอย่างมากในความเร็วระหว่างการจัดสรรหน่วยความจำเมื่อทำงานกับรายการในอาเรย์นั้น (เหมือนเก่า) และการจัดสรรหลายครั้งเมื่ออาเรย์เติบโตขึ้น (ซึ่งเป็นสิ่งที่ระบบหลีกเลี่ยงภายใต้กระโปรงหน้ารถ .

ไม่มีเรื่องนี้แน่นอนจนกว่าคุณจะต้องการทำสิ่งที่ยอดเยี่ยมกับอาร์เรย์ที่มีขนาดใหญ่กว่า จากนั้นมันก็จะ

เนื่องจากดูเหมือนว่ายังไม่มีตัวเลือกใน JS ในขณะนี้เพื่อตั้งค่าความสามารถเริ่มต้นของอาร์เรย์ฉันใช้ต่อไปนี้ ...

var newArrayWithSize = function(size) {
  this.standard = this.standard||[];
  for (var add = size-this.standard.length; add>0; add--) {
   this.standard.push(undefined);// or whatever
  }
  return this.standard.slice(0,size);
}

มีการแลกเปลี่ยนที่เกี่ยวข้อง:

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

แต่ถ้ามันเหมาะกับสิ่งที่คุณทำอาจมีผลตอบแทน เวลาที่ไม่เป็นทางการทำให้

for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}

ที่ค่อนข้างเร็ว (ประมาณ 50ms สำหรับ 10000 ที่กำหนดโดยที่ n = 1000000 ใช้เวลาประมาณ 5 วินาที) และ

for (var n=10000;n>0;n--) {
  var b = [];for (var add=10000;add>0;add--) {
    b.push(undefined);
  }
}

ที่มากกว่าหนึ่งนาที (ประมาณ 90 วินาทีสำหรับ 10000 บนคอนโซลโครเมี่ยมเดียวกันหรือช้ากว่าประมาณ 2000 เท่า) นั่นไม่เพียงเป็นการจัดสรร แต่ยังรวมถึง 10,000 pushes สำหรับ loop ฯลฯ


หากทุกครั้งที่คุณไปถึงจุดสิ้นสุดของอาร์เรย์ที่คุณทำซ้ำความซับซ้อนของการแทรกค่า n ยังคงเป็น O (n) ดังนั้นจึงไม่มีความซับซ้อนแตกต่างกัน (แต่ช้ากว่า)
Tomer Wolberg

ดี @TomerWolberg ฉันเปลี่ยนถ้อยคำของฉันแล้ว มันเป็นเรื่องของวิธีการกดที่มีความซับซ้อนสูงกว่าการเริ่มต้น / คัดลอกของสมาชิกแต่ละคนโดยชิ้น AFAIK ว่าทั้งคู่เป็นเวลาคงที่อย่างน้อยที่สุดพวกเขาอาจจะเป็นดังนั้นฉันจึงใช้คำว่า 'ความเร็ว' แทน
WILS

8

(นี่อาจเป็นความคิดเห็นที่ดีกว่า แต่ยาวเกินไป)

ดังนั้นหลังจากอ่านสิ่งนี้ฉันสงสัยว่าการจัดสรรล่วงหน้านั้นเร็วกว่าจริงหรือไม่เพราะในทางทฤษฎีแล้วมันควรจะเป็น แต่บล็อกนี้ให้เคล็ดลับบางอย่างให้คำปรึกษากับมันhttp://www.html5rocks.com/en/tutorials/speed/v8/

ดังนั้นจึงยังไม่แน่ใจฉันนำไปทดสอบ และดูเหมือนว่าในความเป็นจริงมันจะช้ากว่า

var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
    temp[i]=i;
}
console.log(Date.now()-time);


var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
    temp2[i] = i;
}
console.log(Date.now()-time); 

รหัสนี้ให้ผลตอบแทนต่อไปนี้หลังจากการวิ่งไม่กี่ครั้ง:

$ node main.js 
9
16
$ node main.js 
8
14
$ node main.js 
7
20
$ node main.js 
9
14
$ node main.js 
9
19

3
ที่น่าสนใจที่ดูเหมือนไม่คาดคิดดังนั้นฉันทำทดสอบ JSPerf ผลลัพธ์ของ Chrome ตรงกับการทดสอบ Node ของคุณ แต่ Firefox และ IE เร็วขึ้นเล็กน้อยเมื่อคุณจัดสรรพื้นที่ล่วงหน้าให้กับอาร์เรย์
Michael Martin-Smucker

1
@ MichaelMartin-Smucker รอ ... นี่แปลว่า V8 ไม่ได้ปรับให้สมบูรณ์และสมบูรณ์แบบจริงหรือ?!?!? : P
Zeb McCorkle

1
@ MichaelMartin-Smucker - ฉันเพิ่งรัน jsperf ของคุณใน Chrome เวอร์ชัน 42.0.2311.90 (สำหรับการเจาะจง - การทดสอบใน Chrome 42.0.2311.90 32 บิตบน Windows Server 2008 R2 / 7 64 บิต) และอาร์เรย์ขนาดไดนามิกนั้นช้ากว่า 69% .
Yellen

1
เหมือนกัน (ฉันเขียนการทดสอบโหนดเดิม) ใน Chrome 42.0.2311.90 บน windows ขนาดแบบไดนามิกคือ 81% ช้าลง :) แต่การทดสอบเริ่มแรกของเรามีมากกว่าหนึ่งปีที่แล้ว เวลาเก็บไว้ใน slippin, slippin ....
j03m

1
ที่น่าสนใจ ... จากผลลัพธ์ของ jsperf ดูเหมือนว่าการจัดสรรล่วงหน้าจะเพิ่มขึ้นอย่างมากใน Chrome 38 อนาคต!
Michael Martin-Smucker

8
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6

2
ใช่อย่างไรก็ตาม console.log (arr) ให้[5: 0]สิ่งนี้เป็นอาร์เรย์ที่กระจัดกระจายและอาจไม่ใช่สิ่งที่ต้องการ
dreftymac

7

นี่คือทางออกอื่น

var arr = Array.apply( null, { length: 4 } );
arr;  // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4

อาร์กิวเมนต์แรกของการเป็นวัตถุนี้มีผลผูกพันซึ่งเราไม่สนใจเกี่ยวกับที่นี่เพื่อให้เราตั้งค่าให้apply()null

Array.apply(..)กำลังเรียกใช้Array(..)ฟังก์ชันและกระจาย{ length: 3 }ค่าวัตถุเป็นอาร์กิวเมนต์


ฉันไม่เข้าใจว่าทำไมคำตอบนี้จึงมีการลงคะแนน จริงๆแล้วมันเป็นแฮ็คที่ดี หมายความว่าคุณไม่สามารถใช้new Array(n)เริ่มต้นอาร์เรย์เช่นนี้new Array(n).map(function(notUsed,index){...})ได้ แต่ด้วยวิธีการนี้ตามที่ @zangw พูดถึงคุณสามารถทำได้ +1 จากฉัน
Victor.Palyvoda

3

ตัวสร้างอาร์เรย์มีไวยากรณ์ที่ไม่ชัดเจนและ JSLint สร้างความเจ็บปวดให้กับคุณ

นอกจากนี้ตัวอย่างรหัสของคุณเสียที่สองคำสั่งจะยกvar SyntaxErrorคุณตั้งค่าคุณสมบัติlengthของอาร์เรย์จึงไม่มีความจำเป็นอีกtestvar

เท่าที่ตัวเลือกของคุณarray.lengthเป็น "สะอาด" เท่านั้น คำถามคือทำไมคุณต้องกำหนดขนาดตั้งแต่แรก? พยายาม refactor รหัสของคุณเพื่อกำจัดการอ้างอิงนั้น


ว้าวดูดีในวินาทีvar testนั้น นั่นคือบางส่วนเลอะเทอะคัดลอกและวางในส่วนของฉัน
Michael Martin-Smucker

@IvoWetzel คุณต้องการกำหนดขนาดเพื่อปรับปรุงประสิทธิภาพ อาร์เรย์ JS มีอาร์เรย์แบบไดนามิก หากคุณไม่ได้กำหนดขนาด (หรือค่อนข้างจะเป็นความจุ) JS จะจัดสรรอาร์เรย์ที่มีขนาดเริ่มต้น หากคุณเพิ่มองค์ประกอบมากเกินกว่าที่จะสามารถทำได้ก็จะต้องเพิ่มอาร์เรย์ซึ่งหมายความว่าภายในจะจัดสรรอาร์เรย์ใหม่แล้วคัดลอกองค์ประกอบทั้งหมด
Domi

3

สมมติว่าความยาวของอาร์เรย์นั้นคงที่ ใน Javascript นี่คือสิ่งที่เราทำ:

const intialArray = new Array(specify the value);


2

ตามที่อธิบายไว้ข้างต้นการใช้งานnew Array(size)ค่อนข้างอันตราย แทนที่จะใช้โดยตรงวางไว้ใน "ฟังก์ชั่นผู้สร้างอาร์เรย์" คุณสามารถตรวจสอบได้อย่างง่ายดายว่าฟังก์ชั่นนี้ปราศจากข้อผิดพลาดและหลีกเลี่ยงอันตรายจากการโทรnew Array(size)โดยตรง นอกจากนี้คุณสามารถตั้งค่าเริ่มต้นเป็นทางเลือกได้ createArrayฟังก์ชั่นนี้ทำสิ่งนั้นอย่างแน่นอน:

function createArray(size, defaultVal) {
    var arr = new Array(size);
    if (arguments.length == 2) {
        // optional default value
        for (int i = 0; i < size; ++i) {
            arr[i] = defaultVal;
        }
    }
    return arr;
}

1

คำตอบส่วนใหญ่จะแนะนำให้fillกับอาร์เรย์เพราะมิฉะนั้น"คุณไม่สามารถทำซ้ำมันมากกว่า"แต่นี่ไม่เป็นความจริง forEachคุณสามารถย้ำอาร์เรย์ว่างเพียงแค่ไม่ได้อยู่กับ ในขณะที่ลูปสำหรับลูปและสำหรับลูปฉันทำงานได้ดี

const count = Array(5);

ไม่ทำงาน, ไม่เป็นผล.

console.log('---for each loop:---');
count.forEach((empty, index) => {
    console.log(`counting ${index}`);
});

งานเหล่านี้:

console.log('---for of loop:---');
for (let [index, empty] of count.entries()) {
  console.log(`counting for of loop ${index}`);
}

console.log('---for i loop:---');
for (let i = 0, il = count.length; i < il; ++i) {
  console.log(`counting for i loop ${i}`);
}

console.log('---while loop:---');
let index = 0;
while (index < count.length) { 
  console.log(`counting while loop ${index}`); 
  index++; 
}

ตรวจสอบซอนี้ด้วยตัวอย่างข้างต้น

Angulars ยัง*ngForทำงานได้ดีกับอาเรย์ที่ว่างเปล่า:

<li *ngFor="let empty of count; let i = index" [ngClass]="
  <span>Counting with *ngFor {{i}}</span>
</li>

-1

คุณสามารถตั้งค่าความยาวของอาเรย์โดยใช้ array.length = youValue

ดังนั้นมันจะเป็น

var myArray = [];
myArray.length = yourValue;

-3

เหตุผลที่คุณไม่ควรใช้new Arrayจะถูกแสดงโดยรหัสนี้:

var Array = function () {};

var x = new Array(4);

alert(x.length);  // undefined...

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

นอกจากนี้ดังที่เฟลิกซ์คิงกล่าวว่าอินเทอร์เฟซนั้นไม่สอดคล้องกันเล็กน้อยและอาจนำไปสู่ข้อบกพร่องบางอย่างที่ยากต่อการติดตาม

หากคุณต้องการอาร์เรย์ที่มีความยาว = x เต็มไปด้วยไม่ได้กำหนด (เช่นเดียวกับnew Array(x)) คุณสามารถทำได้ดังนี้:

var x = 4;
var myArray = [];
myArray[x - 1] = undefined;

alert(myArray.length); // 4

48
ตามเหตุผลนี้คุณไม่ควรใช้alertและundefinedเพราะบางรหัสอื่น ๆ อาจยุ่งกับพวกเขา ตัวอย่างที่สองสามารถอ่านได้น้อยกว่าnew Array(4)และไม่ให้ผลลัพธ์ที่เหมือนกัน: jsfiddle.net/73fKd
Alexey Lebedev

25
คำตอบนี้แปลกประหลาด
Marco Demaio

6
คุณไม่สามารถหลีกเลี่ยงผู้คนที่ยุ่งกับวัตถุทั่วโลกใน JavaScript; อย่าทำอย่างนั้นหรือใช้กรอบที่คนอื่นทำ
Richard Connamacher

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