Cách hiệu quả nhất để tạo một mảng JavaScript đầy không?


602

Cách hiệu quả nhất để tạo ra một mảng có độ dài bằng 0 tùy ý trong JavaScript là gì?


7
Một số dữ liệu thực tế về điều này: jsperf.com/zeroarrayjs
Web_Designer

7
ES6 điền cho phép thực hiện điều này tự nhiên.
Salvador Dali

1
mảng = new Array (chiều dài + 1) .joint (ký tự) .split ('');
Jordan Stefanelli

4
CẬP NHẬT 2016 : Một điểm chuẩn tùy chỉnh khác tại đây: jsfiddle.net/basickarl/md5z0Lqq
K - Độc tính trong SO đang tăng lên.

1
let i = 0; Array.from(Array(10), ()=>i++);
Bart Hoekstra

Câu trả lời:


543

ES6 giới thiệu Array.prototype.fill. Nó có thể được sử dụng như thế này:

new Array(len).fill(0);

Không chắc nó có nhanh không, nhưng tôi thích nó vì nó ngắn và tự mô tả.

Nó vẫn chưa có trong IE ( kiểm tra tính tương thích ), nhưng có sẵn một polyfill .


15
điền nhanh new Array(len)là đau đớn chậm. (arr = []).length = len; arr.fill(0);là về giải pháp nhanh nhất tôi từng thấy ở bất cứ đâu ... hoặc ít nhất là bị trói
Pimp Trizkit

7
@PimpTrizkit arr = Array(n)(arr = []).length = nhành xử giống hệt nhau theo thông số kỹ thuật. Trong một số triển khai, người ta có thể nhanh hơn, nhưng tôi không nghĩ có sự khác biệt lớn.
Oriol

2
Chà, tôi đã bắt đầu thử nghiệm nó với các mảng đa chiều và nó dường như tăng tốc đáng kể các trường hợp thử nghiệm của tôi. Vừa mới thực hiện một số thử nghiệm nữa trên FF41 và Chrome45.0.2454.99 m. Vâng, tôi đoán tôi thực sự cần thêm không gian để giải thích bản thân. Hầu hết các thử nghiệm của tôi là thiên vị, tôi sẽ thừa nhận. Nhưng, hãy kiểm tra điều này. Xác định trước một var và chỉ sử dụng dòng này (arr = []).length = 1000; để arr = new Array(1000);kiểm tra tốc độ trong cả Chrome và FF ... newtốc độ rất chậm. Bây giờ, đối với độ dài mảng nhỏ hơn .. giả sử <50 hoặc có abouts ... thì new Array()dường như hoạt động tốt hơn. Nhưng ..
Pimp Trizkit

4
... Tôi sẽ thừa nhận tôi đã bỏ lỡ phần này ... khi tôi thêm dòng thứ hai vào bài kiểm tra ... arr.fill(0) ... mọi thứ đều thay đổi. Bây giờ, việc sử dụng new Array()nhanh hơn trong hầu hết các trường hợp ngoại trừ khi bạn có kích thước mảng> 100000 ... Sau đó, bạn có thể bắt đầu thấy tốc độ tăng trở lại. Nhưng nếu bạn không thực sự phải điền trước nó bằng số không và có thể sử dụng các mảng trống tiêu chuẩn. Sau đó (arr = []).length = xlà điên nhanh trong các trường hợp thử nghiệm của tôi hầu hết thời gian.
Pimp Trizkit

4
Lưu ý rằng để lặp lại qua mảng (ví dụ: map hoặc forEach), các giá trị phải được đặt , nếu không nó sẽ bỏ qua các chỉ mục đó. Các giá trị bạn đặt có thể là bất cứ điều gì bạn muốn - thậm chí không xác định. Ví dụ: thử new Array(5).forEach(val => console.log('hi'));vs new Array(5).fill(undefined).forEach(val => console.log('hi'));.
ArneHugo

387

Mặc dù đây là một chủ đề cũ, tôi muốn thêm 2 xu của mình vào đó. Không chắc mức độ chậm / nhanh của nó, nhưng nó là một lớp lót nhanh. Đây là những gì tôi làm:

Nếu tôi muốn điền trước một số:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]

Nếu tôi muốn điền trước bằng một chuỗi:

Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]

Các câu trả lời khác đã đề xuất:

new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]

nhưng nếu bạn muốn 0 (số) chứ không phải "0" (không trong chuỗi), bạn có thể làm:

new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]

6
Câu trả lời chính xác! Bạn có thể vui lòng giải thích các mẹo với Array.apply(null, new Array(5)).map(...)? Nguyên nhân đơn giản là làm (Mảng mới (5)). Map (...) sẽ không hoạt động như thông số kỹ thuật nói
Dmitry Pashkevich

36
(btw, chúng tôi không thực sự cần new) Khi bạn Array(5)tạo một đối tượng giống như thế này: { length: 5, __proto__: Array.prototype }- hãy thử console.dir( Array(5) ). Chú ý rằng nó không có bất kỳ thuộc tính 0, 1, 2, vv Tuy nhiên, khi bạn applyrằng cho đến Arrayconstructor, nó giống như nói Array(undefined, undefined, undefined, undefined, undefined). Và bạn nhận được một đối tượng giống như thế { length: 5, 0: undefined, 1: undefined...}. maphoạt động trên các thuộc tính 0, 1vv đó là lý do tại sao ví dụ của bạn không hoạt động, nhưng khi bạn sử dụng applynó.
zertosh

4
Tham số đầu tiên .applythực sự là những gì bạn muốn this. Đối với những mục đích thisnày, điều đó không thành vấn đề - chúng tôi chỉ thực sự quan tâm đến "tính năng" lan truyền tham số .apply- vì vậy nó có thể là bất kỳ giá trị nào. Tôi thích nullvì nó rẻ, có lẽ bạn không muốn sử dụng {}hoặc []vì bạn đang bắt đầu một đối tượng mà không có lý do.
zertosh

2
Cũng khởi tạo với kích thước + gán nhanh hơn nhiều so với đẩy. Xem trường hợp thử nghiệm jsperf.com/zero-fill-2d-array
Colin

2
Còn về Array.apply (null, Array (5)). map (x => 0) thì sao? Nó ngắn hơn một chút!
Arch Linux Tux

97

Cách thanh lịch để điền vào một mảng với các giá trị được tính toán trước

Đây là một cách khác để làm điều đó bằng ES6 mà chưa ai đề cập cho đến nay:

> Array.from(Array(3), () => 0)
< [0, 0, 0]

Nó hoạt động bằng cách thông qua một chức năng bản đồ như tham số thứ hai của Array.from.

Trong ví dụ trên, tham số đầu tiên phân bổ một mảng gồm 3 vị trí chứa đầy giá trị undefinedvà sau đó hàm lambda ánh xạ mỗi một trong số chúng thành giá trị 0.

Mặc dù Array(len).fill(0)ngắn hơn, nhưng nó không hoạt động nếu bạn cần điền vào mảng bằng cách thực hiện một số tính toán trước (tôi biết câu hỏi không yêu cầu, nhưng rất nhiều người cuối cùng tìm kiếm điều này) .

Chẳng hạn, nếu bạn cần một mảng có 10 số ngẫu nhiên:

> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]

Nó ngắn gọn (và thanh lịch) hơn tương đương:

const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.round(10 * Math.random());
}

Phương pháp này cũng có thể được sử dụng để tạo các chuỗi số bằng cách tận dụng tham số chỉ mục được cung cấp trong cuộc gọi lại:

> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Phần thưởng trả lời: điền vào một mảng bằng String repeat()

Vì câu trả lời này đang nhận được rất nhiều sự chú ý, tôi cũng muốn thể hiện thủ thuật tuyệt vời này. Mặc dù không hữu ích như câu trả lời chính của tôi, sẽ giới thiệu repeat()phương thức String vẫn chưa được biết đến nhưng rất hữu ích . Đây là mẹo:

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

Mát mẻ, huh? repeat()là một phương pháp rất hữu ích để tạo ra một chuỗi là sự lặp lại của chuỗi ban đầu một số lần nhất định. Sau đó, split()tạo một mảng cho chúng ta, sau đó map()chuyển sang các giá trị chúng ta muốn. Chia nhỏ nó theo các bước:

> "?".repeat(10)
< "??????????"

> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

Rất nhiều thủ đoạn parlor trong bài đó, nhưng hy vọng không ai trong đó sẽ đạt mã sản xuất :)
Eric Grange

Mặc dù repeatmánh khóe chắc chắn không muốn trong sản xuất, nhưng Array.from()hoàn toàn ổn :-)
Lucio Paiva

Không thực sự, Array.from () ở đây về cơ bản là tạo một mảng, lặp qua nó với map (), gọi một hàm trên mỗi mục để tạo một mảng mới, sau đó loại bỏ mảng đầu tiên ... Đối với một mảng nhỏ, điều này có thể là Vô hại, đối với các mảng lớn hơn, đây là kiểu mẫu dẫn đến việc mọi người gọi trình duyệt là "bộ nhớ" :)
Eric Grange

Những người đối phó với mảng lớn nên biết rõ hơn điều này, chắc chắn. Tuy nhiên, đối với các ứng dụng phổ biến, việc tạo một mảng bổ trợ có kích thước thông thường (tối đa 10 nghìn phần tử) sẽ được xử lý ngay lập tức là hoàn toàn tốt (mất cùng thời gian như khi bạn tránh việc tạo mảng bổ sung - được thử nghiệm với Chrome mới nhất). Đối với những trường hợp như vậy, khả năng đọc trở nên quan trọng hơn tối ưu hóa hiệu suất nhỏ. Về thời gian O (n), cần thiết nếu bạn cần tính toán một cái gì đó khác nhau cho mỗi yếu tố (chủ đề chính của câu trả lời của tôi). Cuộc thảo luận này rất thú vị, vui mừng vì bạn đã nêu ra nó!
Lucio Paiva

88

Nói ngắn gọn

Giải pháp nhanh nhất

let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;

Ngắn nhất (tiện dụng) dung dịch (3x chậm hơn cho mảng nhỏ, hơi chậm cho lớn (chậm nhất trên Firefox))

Array(n).fill(0)


Chi tiết

Hôm nay 2020,06,09 Tôi thực hiện các thử nghiệm trên macOS High Sierra 10.13.6 trên các trình duyệt Chrome 83.0, Firefox 77.0 và Safari 13.1. Tôi kiểm tra các giải pháp được lựa chọn cho hai trường hợp thử nghiệm

  • mảng nhỏ - với 10 phần tử - bạn có thể thực hiện kiểm tra ĐÂY
  • mảng lớn - với các phần tử 1M - bạn có thể thực hiện kiểm tra TẠI ĐÂY

Kết luận

  • giải pháp dựa trên new Array(n)+for (N) là giải pháp nhanh nhất cho các mảng nhỏ và mảng lớn (trừ Chrome nhưng vẫn rất nhanh ở đó) và nó được đề xuất là giải pháp trình duyệt chéo nhanh
  • giải pháp dựa trên new Float32Array(n)(I) trả về mảng không điển hình (ví dụ: bạn không thể gọipush(..) vào nó) vì vậy tôi không so sánh kết quả của nó với các giải pháp khác - tuy nhiên giải pháp này là khoảng 10-20x nhanh hơn so với các giải pháp khác cho mảng lớn trên tất cả các trình duyệt
  • giải pháp dựa trên for (L, M, N, O) nhanh chóng cho các mảng nhỏ
  • giải pháp dựa trên fill (B, C) nhanh trên Chrome và Safari nhưng chậm nhất một cách đáng ngạc nhiên trên Firefox cho các mảng lớn. Chúng là trung bình nhanh cho các mảng nhỏ
  • giải pháp dựa trên Array.apply(P) ném lỗi cho mảng lớn

nhập mô tả hình ảnh ở đây

Mã và ví dụ

Dưới đây mã trình bày các giải pháp được sử dụng trong các phép đo

Kết quả ví dụ cho Chrome

nhập mô tả hình ảnh ở đây


Chỉ cần chạy một số thử nghiệm trên Chrome 77 và một vòng lặp đơn giản với push () nhanh gấp hai lần so với fill () ... Tôi tự hỏi những tác dụng phụ tinh tế nào của fill () ngăn cản việc triển khai hiệu quả hơn?
Eric Grange

@EricGrange Tôi cập nhật câu trả lời - ở phía dưới tôi cập nhật liên kết đến băng ghế dự bị với đề xuất của bạn: trường hợp P let a=[]; for(i=n;i--;) a.push(0);- nhưng nó chậm hơn 4 lần so với fill(0)- vì vậy tôi thậm chí sẽ không cập nhật phù thủy hình ảnh đó.
Kamil Kiełczewski

2
Số đo đẹp. Phân tích: G chậm vì thay đổi kích thước mảng ở mỗi lần lặp và thay đổi kích thước có nghĩa là thực hiện cấp phát bộ nhớ mới. A, B, M nhanh vì việc định cỡ chỉ được thực hiện một lần. +1
Roland

@gman thực sự bạn đúng - Tôi không hiểu làm thế nào tôi có thể bỏ lỡ nó - Tôi thực hiện các bài kiểm tra mới và cập nhật câu trả lời với nhiều chi tiết hơn - cảm ơn bạn :)
Kamil Kiełczewski

63

Phương pháp điền vào ES 6 đã được đề cập sẽ xử lý việc này một cách độc đáo. Hầu hết các trình duyệt máy tính để bàn hiện đại đã hỗ trợ các phương thức nguyên mẫu Array cần thiết cho đến ngày nay (Chromium, FF, Edge và Safari) [ 1 ]. Bạn có thể tra cứu chi tiết về MDN . Một ví dụ sử dụng đơn giản là

a = new Array(10).fill(0);

Với sự hỗ trợ của trình duyệt hiện tại, bạn nên thận trọng khi sử dụng điều này trừ khi bạn chắc chắn khán giả của mình sử dụng các trình duyệt Desktop hiện đại.


4
Nếu bạn điền vào một loại tham chiếu, nó sẽ là cùng một tham chiếu trên tất cả chúng. Mảng mới (10) .fill (null) .map (() => []) sẽ là một cách gọn gàng để làm được việc này (đốt tôi ban đầu haha)
John Culviner

4
CẬP NHẬT 2016 : Phương pháp này thổi mọi thứ khác ra khỏi nước, nhấp vào đây để biết điểm chuẩn: jsfiddle.net/basickarl/md5z0Lqq
K - Độc tính trong SO đang tăng lên.

Điều này sẽ làm việc cho mảng. a = Array(10).fill(null).map(() => { return []; });
Andy

2
@AndrewAnthonyGerst Terser:a = Array(10).fill(0).map( _ => [] );
Phrogz

50

Lưu ý thêm vào tháng 8 năm 2013, cập nhật tháng 2 năm 2015: Câu trả lời dưới đây từ năm 2009 liên quan đến loại chung của JavaScript Array. Nó không liên quan đến các mảng được gõ mới hơn được xác định trong ES2015 [và hiện có sẵn trong nhiều trình duyệt], như thế Int32Arrayvà như vậy. Cũng lưu ý rằng ES2015 thêm một fillphương thức cho cả Mảngmảng được gõ , đây có thể là cách hiệu quả nhất để lấp đầy chúng ...

Ngoài ra, nó có thể tạo ra sự khác biệt lớn đối với một số cách triển khai cách bạn tạo mảng. Công cụ V8 của Chrome, đặc biệt, cố gắng sử dụng mảng bộ nhớ liền kề, hiệu quả cao nếu nó nghĩ rằng nó có thể, chỉ chuyển sang mảng dựa trên đối tượng khi cần thiết.


Với hầu hết các ngôn ngữ, nó sẽ được phân bổ trước, sau đó điền vào không, như thế này:

function newFilledArray(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}

Nhưng , mảng JavaScript không thực sự là mảng , chúng là bản đồ khóa / giá trị giống như tất cả các đối tượng JavaScript khác, do đó, không có "phân bổ trước" để làm (đặt độ dài không phân bổ nhiều vị trí cần điền), cũng không Có lý do nào để tin rằng lợi ích của việc đếm ngược về không (điều này chỉ giúp cho việc so sánh trong vòng lặp nhanh) không vượt trội bằng cách thêm các khóa theo thứ tự ngược lại khi việc triển khai có thể tối ưu hóa việc xử lý các phím của chúng liên quan đến mảng trên lý thuyết nói chung bạn sẽ thực hiện chúng theo thứ tự.

Trên thực tế, Matthew Crumley đã chỉ ra rằng việc đếm ngược trên Firefox chậm hơn rõ rệt so với việc đếm ngược, kết quả tôi có thể xác nhận - đó là phần mảng của nó (lặp xuống 0 vẫn nhanh hơn so với lặp đến giới hạn trong một var). Rõ ràng việc thêm các phần tử vào mảng theo thứ tự ngược lại là một hoạt động chậm trên Firefox. Trên thực tế, kết quả thay đổi khá nhiều khi triển khai JavaScript (điều này không đáng ngạc nhiên lắm). Đây là một trang thử nghiệm nhanh và bẩn (bên dưới) để triển khai trình duyệt (rất bẩn, không mang lại hiệu quả trong các thử nghiệm, do đó cung cấp phản hồi tối thiểu và sẽ chạy theo giới hạn thời gian của tập lệnh). Tôi khuyên bạn nên làm mới giữa các bài kiểm tra; FF (ít nhất) làm chậm các bài kiểm tra lặp đi lặp lại nếu bạn không.

Phiên bản khá phức tạp sử dụng Array # concat nhanh hơn một init thẳng trên FF kể từ khoảng 1.000 đến 2.000 mảng phần tử. Tuy nhiên, trên công cụ V8 của Chrome, init thẳng sẽ thắng mỗi lần ...

Đây là trang thử nghiệm ( bản sao trực tiếp ):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zero Init Test Page</title>
<style type='text/css'>
body {
    font-family:    sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
.error {
    color:      red;
}
.winner {
    color:      green;
    font-weight:    bold;
}
</style>
<script type='text/javascript' src='prototype-1.6.0.3.js'></script>
<script type='text/javascript'>
var testdefs = {
    'downpre':  {
        total:  0,
        desc:   "Count down, pre-decrement",
        func:   makeWithCountDownPre
    },
    'downpost': {
        total:  0,
        desc:   "Count down, post-decrement",
        func:   makeWithCountDownPost
    },
    'up':       {
        total:  0,
        desc:   "Count up (normal)",
        func:   makeWithCountUp
    },
    'downandup':  {
        total:  0,
        desc:   "Count down (for loop) and up (for filling)",
        func:   makeWithCountDownArrayUp
    },
    'concat':   {
        total:  0,
        desc:   "Concat",
        func:   makeWithConcat
    }
};

document.observe('dom:loaded', function() {
    var markup, defname;

    markup = "";
    for (defname in testdefs) {
        markup +=
            "<div><input type='checkbox' id='chk_" + defname + "' checked>" +
            "<label for='chk_" + defname + "'>" + testdefs[defname].desc + "</label></div>";
    }
    $('checkboxes').update(markup);
    $('btnTest').observe('click', btnTestClick);
});

function epoch() {
    return (new Date()).getTime();
}

function btnTestClick() {

    // Clear log
    $('log').update('Testing...');

    // Show running
    $('btnTest').disabled = true;

    // Run after a pause while the browser updates display
    btnTestClickPart2.defer();
}
function btnTestClickPart2() {

    try {
        runTests();
    }
    catch (e) {
        log("Exception: " + e);
    }

    // Re-enable the button; we don't yheidl
    $('btnTest').disabled = false;
}

function runTests() {
    var start, time, counter, length, defname, def, results, a, invalid, lowest, s;

    // Get loops and length
    s = $F('txtLoops');
    runcount = parseInt(s);
    if (isNaN(runcount) || runcount <= 0) {
        log("Invalid loops value '" + s + "'");
        return;
    }
    s = $F('txtLength');
    length = parseInt(s);
    if (isNaN(length) || length <= 0) {
        log("Invalid length value '" + s + "'");
        return;
    }

    // Clear log
    $('log').update('');

    // Do it
    for (counter = 0; counter <= runcount; ++counter) {

        for (defname in testdefs) {
            def = testdefs[defname];
            if ($('chk_' + defname).checked) {
                start = epoch();
                a = def.func(length);
                time = epoch() - start;
                if (counter == 0) {
                    // Don't count (warm up), but do check the algorithm works
                    invalid = validateResult(a, length);
                    if (invalid) {
                        log("<span class='error'>FAILURE</span> with def " + defname + ": " + invalid);
                        return;
                    }
                }
                else {
                    // Count this one
                    log("#" + counter + ": " + def.desc + ": " + time + "ms");
                    def.total += time;
                }
            }
        }
    }

    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            def.avg = def.total / runcount;
            if (typeof lowest != 'number' || lowest > def.avg) {
                lowest = def.avg;
            }
        }
    }

    results =
        "<p>Results:" +
        "<br>Length: " + length +
        "<br>Loops: " + runcount +
        "</p>";
    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            results += "<p" + (lowest == def.avg ? " class='winner'" : "") + ">" + def.desc + ", average time: " + def.avg + "ms</p>";
        }
    }
    results += "<hr>";
    $('log').insert({top: results});
}

function validateResult(a, length) {
    var n;

    if (a.length != length) {
        return "Length is wrong";
    }
    for (n = length - 1; n >= 0; --n) {
        if (a[n] != 0) {
            return "Index " + n + " is not zero";
        }
    }
    return undefined;
}

function makeWithCountDownPre(len) {
    var a;

    a = new Array(len);
    while (--len >= 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountDownPost(len) {
    var a;

    a = new Array(len);
    while (len-- > 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountUp(len) {
    var a, i;

    a = new Array(len);
    for (i = 0; i < len; ++i) {
        a[i] = 0;
    }
    return a;
}

function makeWithCountDownArrayUp(len) {
    var a, i;

    a = new Array(len);
    i = 0;
    while (--len >= 0) {
        a[i++] = 0;
    }
    return a;
}

function makeWithConcat(len) {
    var a, rem, currlen;

    if (len == 0) {
        return [];
    }
    a = [0];
    currlen = 1;
    while (currlen < len) {
        rem = len - currlen;
        if (rem < currlen) {
            a = a.concat(a.slice(0, rem));
        }
        else {
            a = a.concat(a);
        }
        currlen = a.length;
    }
    return a;
}

function log(msg) {
    $('log').appendChild(new Element('p').update(msg));
}
</script>
</head>
<body><div>
<label for='txtLength'>Length:</label><input type='text' id='txtLength' value='10000'>
<br><label for='txtLoops'>Loops:</label><input type='text' id='txtLoops' value='10'>
<div id='checkboxes'></div>
<br><input type='button' id='btnTest' value='Test'>
<hr>
<div id='log'></div>
</div></body>
</html>

Không chắc chắn rằng việc điền ngược sẽ có vấn đề ở đây, do bạn chỉ truy cập các phần tử (không xóa chúng) và bạn đã được phân bổ trước. Tôi có lầm không?
Triptych

điểm của phần điền ngược không đặc biệt liên quan đến mảng, nó liên quan đến điều kiện thoát trong một thời gian - chim ưng 0 chấm dứt vòng lặp rất hiệu quả
annakata

(mặc dù tôi vừa nhận thấy mã này không thực sự sử dụng mã đó)
annakata

@annakata, bạn không thể sử dụng điều đó ở đây, vì 0 là một chỉ mục hợp lệ.
Triptych

@triptych: không đúng, tất cả chỉ là đúng thứ tự - xem bài đăng của tôi
annakata

34

Theo mặc định Uint8Array, Uint16ArrayUint32Arraylớp giữ số không như giá trị của nó, do đó bạn không cần bất kỳ kỹ thuật đầy phức tạp, chỉ cần làm:

var ary = new Uint8Array(10);

tất cả các phần tử của mảng arysẽ là số không theo mặc định.


5
Điều này là tốt nhưng lưu ý rằng điều này không thể được đối xử giống như một mảng bình thường, ví dụ Array.isArray(ary)false. Độ dài cũng chỉ đọc để bạn không thể đẩy các mục mới vào đó như vớiary.push
MusikAnimal

Fwiw tất cả các mảng được nhập giữ 0làm giá trị mặc định của chúng.
jfunk

2
@MusikAnimal, Array.from(new Uint8Array(10))sẽ cung cấp một mảng bình thường.
Tomas Langkaas

@TomasLangkaas: Có, nhưng một câu trả lời khác cho thấy rằng chậm hơn khoảng 5 lần so với Array(n).fill(0)Chrome nếu thứ bạn thực sự cần là một Mảng JS. Tuy nhiên, nếu bạn có thể sử dụng TypedArray, thì điều này thậm chí còn nhanh hơn nhiều .fill(0), đặc biệt là nếu bạn có thể sử dụng giá trị khởi tạo mặc định là 0. Dường như không có một hàm tạo nào có giá trị điền và độ dài, như cách mà C ++ std::vectorcó. Dường như đối với bất kỳ giá trị khác không, bạn phải xây dựng TypedArray bằng 0 và sau đó điền vào nó. : /
Peter Cordes

29

Nếu bạn sử dụng ES6, bạn có thể sử dụng Array.from () như thế này:

Array.from({ length: 3 }, () => 0);
//[0, 0, 0]

Có kết quả tương tự như

Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]

Bởi vì

Array.from({ length: 3 })
//[undefined, undefined, undefined]

23
function makeArrayOf(value, length) {
  var arr = [], i = length;
  while (i--) {
    arr[i] = value;
  }
  return arr;
}

makeArrayOf(0, 5); // [0, 0, 0, 0, 0]

makeArrayOf('x', 3); // ['x', 'x', 'x']

Lưu ý rằng whilethường là hiệu quả hơn for-in, forEachvv


3
Không phải là ibiến cục bộ không liên quan? lengthđược truyền bằng giá trị để bạn có thể giảm giá trị trực tiếp.
Sean Sáng

3
Mặc dù điều này ban đầu trông rất tuyệt, nhưng thật không may, việc gán các giá trị tại một điểm tùy ý trong một arary (ví dụ arr[i] = value) rất chậm . Nó nhanh hơn nhiều để lặp lại từ đầu đến cuối và sử dụng arr.push(value). Thật khó chịu, vì tôi thích phương pháp của bạn.
Nick Brunt

19

sử dụng ký hiệu đối tượng

var x = [];

không điền? giống...

var x = [0,0,0,0,0,0];

chứa đầy 'không xác định' ...

var x = new Array(7);

ký hiệu obj với số không

var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;

Là một lưu ý phụ, nếu bạn sửa đổi nguyên mẫu của Array, cả hai

var x = new Array();

var y = [];

sẽ có những sửa đổi nguyên mẫu

Ở mức độ nào, tôi sẽ không quá quan tâm đến hiệu quả hoặc tốc độ của hoạt động này, có rất nhiều điều khác mà bạn có thể sẽ làm lãng phí và tốn kém hơn nhiều so với việc tạo ra một mảng có độ dài tùy ý có chứa số không.


5
Ơ ... không có nulls trong mảng này -var x = new Array(7);
kangax

5
Trên thực tế, mảng không được lấp đầy với bất cứ thứ gì với Mảng mới (n), thậm chí không phải là 'không xác định, nó chỉ đơn giản đặt giá trị độ dài của mảng thành n. Bạn có thể kiểm tra điều này bằng cách gọi (Mảng mới (1)). ForEach (...). forEach không bao giờ thực thi, không giống như nếu bạn gọi nó trên [không xác định].
JussiR

4
new Array(7)không không tạo ra một mảng "tràn ngập không xác định". Nó tạo ra một mảng trống có chiều dài 7.
RobG

1
Bạn có thể muốn xem xét lại các phần câu trả lời của mình vì những gì @RobG đang nói là quan trọng (nếu điều bạn nói là đúng, việc lập bản đồ sẽ dễ dàng hơn nhiều)
Abdo

1
Những ngày này bạn có thể làm (new Array(10)).fill(0).
Javier de la Rosa

18

Tôi đã thử nghiệm tất cả các kết hợp phân bổ trước / không phân bổ trước, đếm lên / xuống và các vòng lặp for / while trong IE 6/7/8, Firefox 3.5, Chrome và Opera.

Các chức năng bên dưới luôn là nhanh nhất hoặc cực kỳ gần gũi trong Firefox, Chrome và IE8 và không chậm hơn nhiều so với nhanh nhất trong Opera và IE 6. Theo tôi, đây cũng là cách đơn giản và rõ ràng nhất. Tôi đã tìm thấy một số trình duyệt trong đó phiên bản vòng lặp while nhanh hơn một chút, vì vậy tôi cũng đưa nó vào để tham khảo.

function newFilledArray(length, val) {
    var array = [];
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}

hoặc là

function newFilledArray(length, val) {
    var array = [];
    var i = 0;
    while (i < length) {
        array[i++] = val;
    }
    return array;
}

1
Bạn cũng có thể ném phần var array = []khai báo vào phần đầu tiên của vòng lặp for, chỉ cách nhau bằng dấu phẩy.
damianb

Tôi thích đề xuất đó của damianb, nhưng hãy nhớ đặt bài tập và dấu phẩy trước khi tăng! `for (var i = 0; i <length; mảng [i] = val, i ++);
trừng phạt 15/03/2015

Làm những gì mà mọi người khác đang thiếu cho cái thứ hai của bạn và đặt độ dài của mảng thành lengthgiá trị đã cho để nó không thay đổi liên tục. Mang lại một mảng dài 1 triệu từ 0 đến 8 trên máy của tôi.
Jonathan Gray

Tôi dường như tăng tốc độ 10 - 15% khi tôi tái cấu trúc giải pháp này thành một lớp lót. for (i = 0, array = []; i < length; ++i) array[i] = val;.. Ít khối hơn? ... dù sao đi nữa, ... nếu tôi đặt array.lengthmảng mới theo chiều dài .. tôi dường như tăng thêm 10% -15% tốc độ trong FF ... trong Chrome, dường như tăng gấp đôi tốc độ -> var i, array = []; array.length = length; while(i < length) array[i++] = val;(vẫn nhanh hơn nếu tôi để nó như một forvòng lặp ... nhưng init không còn cần thiết nữa, vì vậy whiledường như nhanh hơn trên phiên bản này)
Pimp Trizkit

Tôi cũng sẽ lưu ý rằng trong thử nghiệm của tôi. Trong một số kha khá các trường hợp thử nghiệm của tôi, phiên bản cuối cùng dường như trên để thực hiện 3x đến hơn 10x nhanh hơn ... Im không như vậy chắc chắn lý do tại sao ... (mảng kích thước khác nhau được thử nghiệm giữa chrome và FF)
Pimp Trizkit

13

Nếu bạn cần tạo nhiều mảng không có độ dài khác nhau trong quá trình thực thi mã của mình, cách nhanh nhất tôi tìm thấy để đạt được điều này là tạo một mảng 0 một lần , sử dụng một trong các phương pháp được đề cập trong chủ đề này, có độ dài mà bạn biết sẽ không bao giờ vượt quá, và sau đó cắt mảng đó khi cần thiết.

Ví dụ: (sử dụng hàm từ câu trả lời đã chọn ở trên để khởi tạo mảng), tạo một mảng có độ dài maxLpm có độ dài bằng 0 , như một biến hiển thị cho mã cần mảng 0:

var zero = newFilledArray(maxLength, 0);

Bây giờ cắt mảng mọi điều này bạn cần một điền mảng zero chiều dài requiredLength < maxLength :

zero.slice(0, requiredLength);

Tôi đã tạo ra các mảng không đầy hàng ngàn lần trong khi thực thi mã của mình, điều này đã tăng tốc quá trình rất nhiều.


13
function zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}

3
Bạn cũng có thể sử dụng new Array(size+1).join("x").split("x").map(function() { return 0; })để lấy số thực
Yuval

6
@Yuval Hoặc chỉnew Array(size+1).join('0').split('').map(Number)
Paul

11

Tôi không có gì chống lại:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);

được đề xuất bởi Zertosh, nhưng trong một phần mở rộng mảng ES6 mới cho phép bạn thực hiện điều này một cách tự nhiên bằng fillphương pháp. Bây giờ IE edge, Chrome và FF hỗ trợ nó, nhưng kiểm tra bảng tương thích

new Array(3).fill(0)sẽ cung cấp cho bạn [0, 0, 0]. Bạn có thể điền vào mảng với bất kỳ giá trị nào như new Array(5).fill('abc')(ngay cả các đối tượng và các mảng khác).

Trên hết, bạn có thể sửa đổi các mảng trước đó bằng cách điền:

arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end

cung cấp cho bạn: [1, 2, 3, 9, 9, 6]


10

Cách tôi thường làm (và nhanh chóng tuyệt vời) đang sử dụng Uint8Array. Ví dụ: tạo một vectơ không chứa các phần tử 1M:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))

Tôi là người dùng Linux và luôn làm việc cho tôi, nhưng một khi một người bạn sử dụng máy Mac có một số yếu tố khác không. Tôi nghĩ rằng máy của anh ta đã gặp trục trặc, nhưng đây vẫn là cách an toàn nhất mà chúng tôi tìm thấy để khắc phục nó:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 

Đã chỉnh sửa

Chrome 25.0.1364.160

  1. Frederik Gottlieb - 6,43
  2. Sam Barnum - 4,83
  3. Eli - 3,68
  4. Giô-suê 2,91
  5. Mathew Crumley - 2,67
  6. bd-2,55
  7. Gạo Allen - 2.11
  8. kangax - 0,68
  9. Tj. Đám đông - 0,67
  10. zertosh - LRI

Firefox 20.0

  1. Gạo Allen - 1,85
  2. Giô-suê - 1,82
  3. Mathew Crumley - 1,79
  4. bduran - 1.37
  5. Frederik Gottlieb - 0,67
  6. Sam Barnum - 0,63
  7. Eli - 0,59
  8. kagax - 0,13
  9. Tj. Đám đông - 0,13
  10. zertosh - LRI

Thiếu bài kiểm tra quan trọng nhất (ít nhất là đối với tôi): bài kiểm tra Node.js. Tôi nghi ngờ nó gần với điểm chuẩn của Chrome.


Đây là cách hiệu quả nhất cho ngón tay và mắt của tôi. Nhưng Chrome rất chậm (phù hợp với jsperf. Chậm hơn 99%).
Orwellophile

1
Tôi tự hỏi liệu sự cố trên máy Mac của bạn của bạn có liên quan đến: stackoverflow.com/questions/39129200/ Lời hoặc có thể Array.slice không xử lý UInt8Array và rò rỉ bộ nhớ chưa được khởi tạo? (một vấn đề bảo mật!).
robocat

@robocat Bắt tốt! Nếu tôi nhớ rõ, chúng tôi đã sử dụng Node.js 0,6 hoặc 0,8. Chúng tôi đã nghĩ về một số loại rò rỉ nhưng chúng tôi không thể tái tạo nó với ngăn xếp sản xuất nên chúng tôi quyết định bỏ qua nó.
durum

10

Sử dụng lodash hoặc gạch dưới

_.range(0, length - 1, 0);

Hoặc nếu bạn có một mảng hiện có và bạn muốn một mảng có cùng độ dài

array.map(_.constant(0));

Rất vui vì bạn đã thêm câu trả lời này, khi tôi sử dụng dấu gạch dưới và tôi biết có một cái gì đó cho điều này ... nhưng vẫn chưa thể tìm thấy nó. Tôi chỉ ước mình có thể tạo ra các mảng đối tượng bằng cách này
PandaWood

@PandaWood _.range (0, chiều dài -1, 0) .map (Object.new), tôi nghĩ vậy.
djechlin

Nên _.range(0, length, 0), tôi tin. Lodash không bao gồm giá trị cuối
user4815162342

9

Giải pháp ES6:

[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]

8

Kể từ ECMAScript2016 , có một lựa chọn rõ ràng cho các mảng lớn.

Vì câu trả lời này vẫn hiển thị gần đầu trên các tìm kiếm của google, đây là câu trả lời cho năm 2017.

Đây là một jsbench hiện tại với một vài chục phương thức phổ biến, bao gồm nhiều phương pháp được đề xuất cho đến nay cho câu hỏi này. Nếu bạn tìm thấy một phương pháp tốt hơn xin vui lòng thêm, ngã ba và chia sẻ.

Tôi muốn lưu ý rằng không có cách hiệu quả nhất thực sự để tạo ra một mảng có độ dài bằng 0 tùy ý. Bạn có thể tối ưu hóa cho tốc độ, hoặc cho sự rõ ràng và khả năng bảo trì - có thể được coi là sự lựa chọn hiệu quả hơn tùy thuộc vào nhu cầu của dự án.

Khi tối ưu hóa tốc độ, bạn muốn: tạo mảng bằng cú pháp bằng chữ; đặt độ dài, khởi tạo biến lặp và lặp qua mảng bằng vòng lặp while. Đây là một ví dụ.

const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
  arr[i] = 0;
  i++;
}

Một cách thực hiện khác có thể là:

(arr = []).length = n;
let i = 0;
while (i < n) {
    arr[i] = 0;
    i++;
}

Nhưng tôi thực sự không khuyến khích sử dụng phương pháp cấy ghép thứ hai này trong thực tế vì nó không rõ ràng và không cho phép bạn duy trì phạm vi khối trên biến mảng của mình.

Chúng nhanh hơn đáng kể so với điền vào một vòng lặp for và nhanh hơn khoảng 90% so với phương pháp tiêu chuẩn

const arr = Array(n).fill(0);

Nhưng phương pháp điền này vẫn là lựa chọn hiệu quả nhất cho các mảng nhỏ hơn do tính rõ ràng, đồng nhất và khả năng bảo trì của nó. Sự khác biệt về hiệu suất có thể sẽ không giết bạn trừ khi bạn tạo ra nhiều mảng với độ dài theo thứ tự hàng nghìn trở lên.

Một vài lưu ý quan trọng khác. Hầu hết các hướng dẫn phong cách khuyên bạn không còn sử dụng varmà không có lý do rất đặc biệt khi sử dụng ES6 trở lên. Sử dụng constcho các biến sẽ không được xác định lại và letcho các biến sẽ. Các MDNHướng dẫn Phong cách Airbnb của là nơi tuyệt vời để đi để biết thêm thông tin về thực hành tốt nhất. Các câu hỏi không phải là về cú pháp, nhưng điều quan trọng là mọi người mới biết về JS đều biết về các tiêu chuẩn mới này khi tìm kiếm thông qua các câu trả lời cũ và mới.


8

Để tạo một Mảng hoàn toàn mới

new Array(arrayLength).fill(0);

Để thêm một số giá trị ở cuối Mảng hiện có

[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]

Thí dụ

//**To create an all new Array**

console.log(new Array(5).fill(0));

//**To add some values at the end of an existing Array**

let existingArray = [1,2,3]

console.log([...existingArray, ...new Array(5).fill(0)]);


6

Không thấy phương pháp này trong câu trả lời, vì vậy đây là:

"0".repeat( 200 ).split("").map( parseFloat )

Kết quả là bạn sẽ nhận được mảng có giá trị bằng không có độ dài 200:

[ 0, 0, 0, 0, ... 0 ]

Tôi không chắc chắn về hiệu suất của mã này, nhưng nó không phải là vấn đề nếu bạn sử dụng nó cho các mảng tương đối nhỏ.


5
Không phải là nhanh nhất hay ngắn nhất mà là một đóng góp tốt đẹp cho sự đa dạng của các giải pháp.
7vujy0f0hy


4

Đây concatlà phiên bản nhanh hơn nhiều trong các thử nghiệm của tôi trên Chrome (2013/03/21). Khoảng 200ms cho 10.000.000 phần tử so với 675 cho init thẳng.

function filledArray(len, value) {
    if (len <= 0) return [];
    var result = [value];
    while (result.length < len/2) {
        result = result.concat(result);
    }
    return result.concat(result.slice(0, len-result.length));
}

Phần thưởng: nếu bạn muốn điền vào mảng của mình bằng Chuỗi, đây là một cách ngắn gọn để làm điều đó (không hoàn toàn nhanh như concatvậy):

function filledArrayString(len, value) {
    return new Array(len+1).join(value).split('');
}

2
Ok, hoang dã. Đó là CÁCH nhanh hơn so với sử dụng Mảng mới (len). NHƯNG! Tôi đang thấy trong Chrome rằng các lần đọc dữ liệu tiếp theo mất nhiều thời gian hơn. Dưới đây là một số dấu thời gian để hiển thị ý tôi là: (Sử dụng Mảng mới (len)) 0.365: Tạo Mảng 4.526: Thực hiện Kết hợp 10,75: Hoàn thành kết hợp (Sử dụng concat) 0,39: Tạo Mảng 0,591: Thực hiện Chuyển đổi // OMG, CÁCH nhanh hơn 18.056: Hoàn thành thuyết phục
Brooks

4

Tôi đã thử nghiệm câu trả lời tuyệt vời của TJ Crowder và đã đưa ra một sự hợp nhất đệ quy dựa trên giải pháp concat vượt trội hơn bất kỳ thử nghiệm nào trong Chrome (tôi không thử nghiệm các trình duyệt khác).

function makeRec(len, acc) {
    if (acc == null) acc = [];
    if (len <= 1) return acc;
    var b = makeRec(len >> 1, [0]);
    b = b.concat(b);
    if (len & 1) b = b.concat([0]);
    return b;
},

gọi phương thức với makeRec(29).



4

Có thể đáng để chỉ ra, Array.prototype.fillđã được thêm vào như một phần của đề xuất ECMAScript 6 (Harmony) . Tôi thà đi với polyfill được viết dưới đây, trước khi xem xét các tùy chọn khác được đề cập trên chuỗi.

if (!Array.prototype.fill) {
  Array.prototype.fill = function(value) {

    // Steps 1-2.
    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    var O = Object(this);

    // Steps 3-5.
    var len = O.length >>> 0;

    // Steps 6-7.
    var start = arguments[1];
    var relativeStart = start >> 0;

    // Step 8.
    var k = relativeStart < 0 ?
      Math.max(len + relativeStart, 0) :
      Math.min(relativeStart, len);

    // Steps 9-10.
    var end = arguments[2];
    var relativeEnd = end === undefined ?
      len : end >> 0;

    // Step 11.
    var final = relativeEnd < 0 ?
      Math.max(len + relativeEnd, 0) :
      Math.min(relativeEnd, len);

    // Step 12.
    while (k < final) {
      O[k] = value;
      k++;
    }

    // Step 13.
    return O;
  };
}

4

Ngắn nhất cho mã vòng lặp

a=i=[];for(;i<100;)a[i++]=0;

edit:
for(a=i=[];i<100;)a[i++]=0;
or
for(a=[],i=100;i--;)a[i]=0;

Phiên bản var an toàn

var a=[],i=0;for(;i<100;)a[i++]=0;

edit:
for(var i=100,a=[];i--;)a[i]=0;

2
Cho rằng độ dài là một biến xác định n, điều này sẽ ngắn hơn:for(var a=[];n--;a[n]=0);
Tomas Langkaas 8/12/2016


3

Chức năng nhanh nhất của tôi sẽ là:

function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds

Sử dụng tính năng đẩy và dịch chuyển riêng để thêm các mục vào mảng nhanh hơn nhiều (khoảng 10 lần) so với khai báo phạm vi mảng và tham chiếu từng mục để đặt giá trị của nó.

fyi: Tôi liên tục nhận được thời gian nhanh hơn với vòng lặp đầu tiên, đó là đếm ngược, khi chạy nó trong fireorms (phần mở rộng firefox).

var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
    a.push(0);
    len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
    a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds

Tôi muốn biết TJ Crowder làm gì với điều đó? :-)


Bạn có thể làm cho nó nhanh hơn bằng cách thay đổi nó thành while (len--).. mất thời gian xử lý của tôi từ khoảng 60ms đến khoảng 54ms
nickf

Câu trả lời của Matthew Crumbly vẫn thực sự đánh bại điều này (30ms)!
nickf

3

Tôi biết tôi đã có proto'd này ở đâu đó :)

Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

var a = (new Array(5)).init(0);

var b = [].init(0,4);

Chỉnh sửa: kiểm tra

Để đáp ứng với Joshua và các phương pháp khác, tôi đã chạy điểm chuẩn của riêng mình và tôi thấy kết quả hoàn toàn khác với những phương pháp được báo cáo.

Đây là những gì tôi đã thử nghiệm:

//my original method
Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this.push(x); }
    return this;
}

//joshua's method
function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

//test m1 and m2 with short arrays many times 10K * 10

var a = new Date();
for(var i=0; i<10000; i++)
{
    var t1 = [].init(0,10);
}
var A = new Date();

var b = new Date();
for(var i=0; i<10000; i++)
{
    var t2 = [].init2(0,10);
}
var B = new Date();

//test m1 and m2 with long array created once 100K

var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();

var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();

//test m3 with short array many times 10K * 10

var e = new Date();
for(var i=0; i<10000; i++)
{
    var t5 = newFilledArray(10,0);
}
var E = new Date();

//test m3 with long array created once 100K

var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();

Các kết quả:

IE7 deltas:
dA=156
dB=359
dC=125
dD=375
dE=468
dF=412

FF3.5 deltas:
dA=6
dB=13
dC=63
dD=8
dE=12
dF=8

Vì vậy, bằng cách tính toán đẩy của tôi thực sự là chậm hơn nói chung nhưng hoạt động tốt hơn với các mảng dài hơn trong FF nhưng tệ hơn trong IE chỉ nói chung là bất ngờ (quel ngạc nhiên).


Tôi vừa thử nghiệm điều này: phương pháp thứ hai ( b = []...) nhanh hơn 10-15% so với phương pháp thứ nhất, nhưng nó chậm hơn 10 lần so với câu trả lời của Joshua.
nickf

Tôi biết đây là một bài viết cổ xưa . Nhưng có lẽ nó vẫn được người khác quan tâm (như tôi). Do đó, tôi muốn đề xuất một danh sách cho chức năng nguyên mẫu: bao gồm một else {this.length=n;}sau this.length-check. Điều này sẽ rút ngắn một mảng đã có sẵn nếu cần thiết khi định nghĩa lại initnó thành một độ dài khác n.
xe10m

2

Hàm ẩn danh:

(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

Ngắn hơn một chút với vòng lặp for:

(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

Làm việc với bất kỳ Object, chỉ cần thay đổi những gì bên trong this.push().

Bạn thậm chí có thể lưu chức năng:

function fill(size, content) {
  for(;size--;this.push(content));
  return this;
}

Gọi nó bằng cách sử dụng:

var helloArray = fill.call([], 5, 'hello');
// => ['hello', 'hello', 'hello', 'hello', 'hello']

Thêm các phần tử vào một mảng đã có sẵn:

var helloWorldArray = fill.call(helloArray, 5, 'world');
// => ['hello', 'hello', 'hello', 'hello', 'hello', 'world', 'world', 'world', 'world', 'world']

Hiệu suất: http://jsperf.com/zero-filling-array-creation/25

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.