𝗥𝗲𝘀𝗲𝗮𝗿𝗰𝗵 𝗔𝗻𝗱 𝗥𝗲𝘀𝘂𝗹𝘁𝘀
Faktanya, tes kinerja di jsperf dan memeriksa beberapa hal di konsol dilakukan. Untuk penelitian, situs web irt.org digunakan. Di bawah ini adalah kumpulan dari semua sumber ini disatukan ditambah fungsi contoh di bagian bawah.
╔═══════════════╦══════╦═════════════════╦════════ ═══════╦═════════╦══════════╗
║ Metode ║Concat║slice & push.apply ║ push.apply x2 ║ ForLoop ║Sebarluaskan ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ mOps / Sec ║179 ║104 ║ 76 ║ 81 ║28 ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ Jarang array ║YES! ║Hanya diiris ║ tidak ║ Mungkin 2 ║tidak ║
║ jarang disimpan ║ ║array (argumen 1) ║ ║ ║ ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ Dukungan ║MSIE 4║MSIE 5.5 ║ MSIE 5.5 ║ MSIE 4 ║Edge 12 ║
║ ( sumber ) ║NNav 4║NNav 4,06 ║ NNav 4,06 ║ NNav 3 ║ MSIE NNav ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║Array-like act║no ║Hanya yang didorong ║ YA! ║ YA! ║Jika punya ║
║like array ║ ║array (2 arg) ║ ║ ║iterator 1 ║
╚═══════════════╩══════╩═════════════════╩════════ ═══════╩═════════╩══════════╝
1 Jika objek mirip array tidak memiliki properti Symbol.iterator , maka cobalah
untuk menyebarkannya akan melempar pengecualian.
2 Tergantung pada kode. Contoh kode berikut "YA" menjaga jarangnya.
function mergeCopyTogether(inputOne, inputTwo){
var oneLen = inputOne.length, twoLen = inputTwo.length;
var newArr = [], newLen = newArr.length = oneLen + twoLen;
for (var i=0, tmp=inputOne[0]; i !== oneLen; ++i) {
tmp = inputOne[i];
if (tmp !== undefined || inputOne.hasOwnProperty(i)) newArr[i] = tmp;
}
for (var two=0; i !== newLen; ++i, ++two) {
tmp = inputTwo[two];
if (tmp !== undefined || inputTwo.hasOwnProperty(two)) newArr[i] = tmp;
}
return newArr;
}
Seperti yang terlihat di atas, saya berpendapat bahwa Concat hampir selalu merupakan cara yang baik untuk kinerja dan kemampuan untuk mempertahankan jarangnya array cadangan. Kemudian, untuk array-like (seperti DOMNodeLists like document.body.children
), saya akan merekomendasikan menggunakan for loop karena keduanya adalah yang paling berkinerja 2 dan satu-satunya metode lain yang mempertahankan array jarang. Di bawah ini, kita akan dengan cepat membahas apa yang dimaksud dengan array jarang dan array-suka untuk menghilangkan kebingungan.
𝗧𝗵𝗲 𝗙𝘂𝘁𝘂𝗿𝗲
Pada awalnya, beberapa orang mungkin berpikir bahwa ini adalah kebetulan dan bahwa vendor browser pada akhirnya akan mengoptimalkan Array.prototype.push agar cukup cepat untuk mengalahkan Array.prototype.concat. SALAH! Array.prototype.concat akan selalu lebih cepat (setidaknya pada prinsipnya) karena ini adalah copy-n-paste sederhana atas data. Di bawah ini adalah diagram persuado-visual yang disederhanakan dari apa yang terlihat seperti implementasi array 32-bit (harap dicatat implementasi nyata BANYAK yang lebih rumit)
Byte ║ Data di sini
═════╬═══════════
0x00 ║ int nonNumericPropertiesLength = 0x00000000
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 ║ panjang int = 0x00000001
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 ║ nilai intIndex = 0x00000000
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 ║ int valueType = JS_PRIMITIVE_NUMBER
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 ║ uintptr_t valuePointer = 0x38d9eb60 (atau di mana pun itu ada dalam memori)
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
Seperti yang terlihat di atas, semua yang perlu Anda lakukan untuk menyalin sesuatu seperti itu hampir sesederhana menyalinnya byte demi byte. Dengan Array.prototype.push.apply, ini lebih dari sekadar copy-n-paste ke data. ".Apply" harus memeriksa setiap indeks dalam array dan mengubahnya menjadi seperangkat argumen sebelum meneruskannya ke Array.prototype.push. Kemudian, Array.prototype.push juga harus mengalokasikan lebih banyak memori setiap kali, dan (untuk beberapa implementasi browser) bahkan mungkin menghitung ulang beberapa data pencarian posisi untuk sparseness.
Cara alternatif untuk memikirkannya adalah ini. Sumber array satu adalah tumpukan besar kertas dijepit bersama. Array sumber dua juga merupakan tumpukan kertas lain. Apakah akan lebih cepat bagimu untuk melakukannya
- Pergi ke toko, beli cukup kertas yang dibutuhkan untuk salinan setiap larik sumber. Kemudian letakkan masing-masing tumpukan larik sumber kertas melalui mesin fotokopi dan menjilid dua salinan yang dihasilkan.
- Pergi ke toko, beli kertas secukupnya untuk satu salinan dari array sumber pertama. Kemudian, salin array sumber ke kertas baru dengan tangan, memastikan untuk mengisi setiap titik kosong yang kosong. Kemudian, kembali ke toko, beli kertas yang cukup untuk array sumber kedua. Kemudian, buka array sumber kedua dan salin sambil memastikan tidak ada celah kosong di salinan. Kemudian, pokok semua kertas yang disalin bersama.
Dalam analogi di atas, opsi # 1 mewakili Array.prototype.concat sedangkan # 2 mewakili Array.prototype.push.apply. Mari kita menguji ini dengan JSperf serupa yang hanya berbeda dalam hal ini menguji metode over array jarang, bukan solid array. Orang dapat menemukannya di sini .
Oleh karena itu, saya menyatakan kasus saya bahwa masa depan kinerja untuk kasus penggunaan khusus ini tidak terletak pada Array.prototype.push, melainkan pada Array.prototype.concat.
𝗖𝗹𝗮𝗿𝗶𝗳𝗶𝗰𝗮𝘁𝗶𝗼𝗻𝘀
𝗦𝗽𝗮𝗿𝗲 𝗔𝗿𝗿𝗮𝘆𝘀
Ketika beberapa anggota array hilang. Sebagai contoh:
// This is just as an example. In actual code,
// do not mix different types like this.
var mySparseArray = [];
mySparseArray[0] = "foo";
mySparseArray[10] = undefined;
mySparseArray[11] = {};
mySparseArray[12] = 10;
mySparseArray[17] = "bar";
console.log("Length: ", mySparseArray.length);
console.log("0 in it: ", 0 in mySparseArray);
console.log("arr[0]: ", mySparseArray[0]);
console.log("10 in it: ", 10 in mySparseArray);
console.log("arr[10] ", mySparseArray[10]);
console.log("20 in it: ", 20 in mySparseArray);
console.log("arr[20]: ", mySparseArray[20]);
Atau, javascript memungkinkan Anda untuk menginisialisasi array cadangan dengan mudah.
var mySparseArray = ["foo",,,,,,,,,,undefined,{},10,,,,,"bar"];
𝗔𝗿𝗿𝗮𝘆-𝗟𝗶𝗸𝗲𝘀
Seperti array adalah objek yang memiliki setidaknya length
properti, tetapi tidak diinisialisasi dengan new Array
atau []
; Sebagai contoh, objek di bawah ini diklasifikasikan sebagai array-like.
{0: "foo", 1: "bar", panjang: 2}
document.body.children
Uint8Array baru (3)
- Ini seperti array karena walaupun array (n) (diketik), memaksa ke array mengubah konstruktor.
(function () {return argumen}) ()
Amati apa yang terjadi menggunakan metode yang memaksa-suka array ke dalam array seperti slice.
var slice = Array.prototype.slice;
// For arrays:
console.log(slice.call(["not an array-like, rather a real array"]));
// For array-likes:
console.log(slice.call({0: "foo", 1: "bar", length:2}));
console.log(slice.call(document.body.children));
console.log(slice.call(new Uint8Array(3)));
console.log(slice.call( function(){return arguments}() ));
- CATATAN: Adalah praktik yang buruk untuk memanggil slice pada argumen fungsi karena kinerja.
Amati apa yang terjadi dengan menggunakan metode yang tidak memaksa array-like ke dalam array seperti concat.
var empty = [];
// For arrays:
console.log(empty.concat(["not an array-like, rather a real array"]));
// For array-likes:
console.log(empty.concat({0: "foo", 1: "bar", length:2}));
console.log(empty.concat(document.body.children));
console.log(empty.concat(new Uint8Array(3)));
console.log(empty.concat( function(){return arguments}() ));