[]
adalah sebuah array.
Array ini tidak digunakan sama sekali.
Itu sedang diletakkan di halaman, karena menggunakan array memberi Anda akses ke prototipe array, seperti .forEach
.
Ini lebih cepat daripada mengetik Array.prototype.forEach.call(...);
Berikutnya, forEach
adalah fungsi yang mengambil fungsi sebagai input ...
[1,2,3].forEach(function (num) { console.log(num); });
... dan untuk setiap elemen di this
( di mana this
seperti array, karena memiliki length
dan Anda dapat mengakses bagian-bagiannya seperti this[1]
) itu akan melewati tiga hal:
- elemen dalam array
- indeks elemen (elemen ketiga akan berlalu
2
)
- referensi ke array
Terakhir, .call
adalah prototipe yang memiliki fungsi (ini adalah fungsi yang dipanggil pada fungsi lain).
.call
akan mengambil argumen pertamanya dan mengganti this
bagian dalam fungsi biasa dengan apa pun yang Anda lewati call
, sebagai argumen pertama ( undefined
atau null
akan digunakan window
dalam JS sehari-hari, atau akan menjadi apa pun yang Anda berikan, jika dalam "mode ketat"). Sisa argumen akan diteruskan ke fungsi asli.
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
Oleh karena itu, Anda membuat cara cepat untuk memanggil forEach
fungsi, dan Anda mengubah this
dari array kosong ke daftar semua <a>
tag, dan untuk setiap <a>
pesanan, Anda memanggil fungsi yang disediakan.
EDIT
Kesimpulan logis / Pembersihan
Di bawah ini, ada tautan ke artikel yang menyarankan agar kami membatalkan upaya pemrograman fungsional, dan tetap berpegang pada pengulangan inline manual, setiap saat, karena solusi ini bersifat hack-ish dan tidak sedap dipandang.
Saya akan mengatakan bahwa sementara .forEach
kurang bermanfaat daripada rekan-rekan, .map(transformer)
, .filter(predicate)
, .reduce(combiner, initialValue)
, masih melayani tujuan ketika semua Anda benar-benar ingin lakukan adalah memodifikasi dunia luar (bukan array), n-kali, sementara memiliki akses ke baik arr[i]
atau i
.
Jadi bagaimana kita menghadapi perbedaan ini, karena Motto jelas adalah orang yang berbakat dan berpengetahuan luas, dan saya ingin membayangkan bahwa saya tahu apa yang saya lakukan / ke mana saya akan pergi (sekarang dan kemudian ... ... lainnya kali ini adalah pembelajaran kepala-pertama)?
Jawabannya sebenarnya cukup sederhana, dan sesuatu Paman Bob dan Sir Crockford akan menghadapinya, karena pengawasan:
bersihkan .
function toArray (arrLike) { // or asArray(), or array(), or *whatever*
return [].slice.call(arrLike);
}
var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);
Sekarang, jika Anda mempertanyakan apakah Anda perlu melakukan ini, sendiri, jawabannya mungkin tidak ...
Hal yang pasti ini dilakukan oleh ... ... setiap (?) Perpustakaan dengan fitur tingkat tinggi hari ini.
Jika Anda menggunakan lodash atau garis bawah atau bahkan jQuery, mereka semua akan memiliki cara untuk mengambil set elemen, dan melakukan aksi n-kali.
Jika Anda tidak menggunakan hal seperti itu, maka tentu saja, tulis sendiri.
lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
var others = lib.array(arguments, 1);
return others.reduce(appendKeys, subject);
};
Pembaruan untuk ES6 (ES2015) dan Beyond
Tidak hanya metode pembantu slice( )
/ array( )
/ etc akan membuat hidup lebih mudah bagi orang-orang yang ingin menggunakan daftar seperti mereka menggunakan array (sebagaimana mestinya), tetapi untuk orang-orang yang memiliki kemewahan beroperasi di browser ES6 + yang relatif dekat di masa depan, atau "pengalihan" di Babel hari ini, Anda memiliki fitur bahasa bawaan, yang membuat hal semacam ini tidak perlu.
function countArgs (...allArgs) {
return allArgs.length;
}
function logArgs (...allArgs) {
return allArgs.forEach(arg => console.log(arg));
}
function extend (subject, ...others) { /* return ... */ }
var nodeArray = [ ...nodeList1, ...nodeList2 ];
Super bersih, dan sangat bermanfaat.
Cari operator Istirahat dan Sebarkan ; coba mereka di situs BabelJS; jika tumpukan teknologi Anda dalam urutan, gunakan mereka dalam produksi dengan Babel dan langkah membangun.
Tidak ada alasan bagus untuk tidak dapat menggunakan transformasi dari non-array menjadi array ... ... hanya saja jangan membuat kekacauan kode Anda melakukan apa-apa selain menempelkan garis jelek yang sama, di mana-mana.
.call
tidak mengubah nilaithis
, itulah sebabnya Anda menggunakancall
dengan forEach. Jika forEach terlihat seperti ituforEach (fn) { var i = 0; var len = this.length; for (; i < length; i += 1) { fn( this[i], i, this ); }
maka dengan mengubahthis
dengan mengatakanforEach.call( newArrLike )
berarti bahwa ia akan menggunakan objek baru tersebut sebagaithis
..call
tidak mengubah nilaithis
di dalam apa yang Anda berikanforEach
,.call
mengubah nilaithis
di dalam forEach . Jika Anda bingung mengapathis
tidak diteruskanforEach
ke fungsi yang ingin Anda panggil, Anda harus melihat perilakuthis
dalam JavaScript. Sebagai tambahan, hanya berlaku di sini (dan memetakan / memfilter / mengurangi), ada argumen keduaforEach
, yang menetapkanthis
di dalam fungsiarr.forEach(fn, thisInFn)
atau[].forEach.call(arrLike, fn, thisInFn);
atau hanya menggunakan.bind
;arr.forEach(fn.bind(thisInFn));
[]
hanya ada sebagai sebuah array, sehingga Anda dapat.call
dengan.forEach
metode ini, dan ubahthis
ke set yang ingin Anda kerjakan..call
terlihat seperti ini:function (thisArg, a, b, c) { var method = this; method(a, b, c); }
kecuali bahwa ada internal yang hitam-sihir untuk setthis
dalammethod
menyamai apa yang Anda lulus sebagaithisArg
.The
querySelectorAll
Metode mengembalikanNodeList
, yang mirip dengan array, tapi itu tidak cukup array. Oleh karena itu, ia tidak memilikiforEach
metode (yang mewarisi objek array melaluiArray.prototype
).Karena a
NodeList
mirip dengan array, metode array akan benar-benar bekerja di atasnya, jadi dengan menggunakan[].forEach.call
Anda memanggilArray.prototype.forEach
metode dalam konteksNodeList
, seolah-olah Anda bisa melakukannyayourNodeList.forEach(/*...*/)
.Perhatikan bahwa literal array kosong hanyalah jalan pintas ke versi yang diperluas, yang mungkin akan sering Anda lihat juga:
sumber
[].forEach.call(['a','b'], cb)
lebih['a','b'].forEach(cb)
dalam aplikasi sehari-hari dengan array standar, hanya ketika mencoba untuk beralih di atas struktur seperti array yang tidakforEach
memiliki prototipe mereka sendiri? Apakah itu benar?[].forEach()
:)var section = document.querySelectorAll(".section"); section.forEach((item)=>{ console.log(item.offsetTop) })
berfungsi dengan baikforEach
pada array, tetapi tidak objek NodeList)Jawaban lain telah menjelaskan kode ini dengan sangat baik, jadi saya hanya akan menambahkan saran.
Ini adalah contoh kode yang baik yang harus di refactored untuk kesederhanaan dan kejelasan. Alih-alih menggunakan
[].forEach.call()
atauArray.prototype.forEach.call()
setiap kali Anda melakukan ini, buatlah fungsi sederhana darinya:Sekarang Anda dapat memanggil fungsi ini alih-alih kode yang lebih rumit dan tidak jelas:
sumber
Itu bisa lebih baik menggunakan tulisan
Apa yang dilakukan adalah
document.querySelectorAll('a')
mengembalikan objek yang mirip dengan array, tetapi tidak mewarisi dariArray
tipe. Jadi kita memanggilforEach
metode dariArray.prototype
objek dengan konteks sebagai nilai yang dikembalikan olehdocument.querySelectorAll('a')
sumber
Pada dasarnya sama dengan:
sumber
Ingin memperbarui pertanyaan lama ini:
Alasan untuk menggunakan
[].foreach.call()
untuk mengulang elemen di browser modern sebagian besar sudah berakhir. Kita bisa menggunakandocument.querySelectorAll("a").foreach()
secara langsung.sumber
Array kosong memiliki properti
forEach
dalam prototipenya yang merupakan objek Function. (Array kosong hanyalah cara mudah untuk mendapatkan referensi keforEach
fungsi yang dimiliki semuaArray
objek.) Objek fungsi, pada gilirannya, memilikicall
properti yang juga merupakan fungsi. Saat Anda menjalankan fungsi Functioncall
, ia menjalankan function dengan argumen yang diberikan. Argumen pertama menjadithis
fungsi yang disebut.Anda dapat menemukan dokumentasi untuk
call
fungsi di sini . DokumentasiforEach
ada di sini .sumber
Cukup tambahkan satu baris:
Dan voila!
Nikmati :-)
Peringatan: NodeList adalah kelas global. Jangan gunakan rekomendasi ini jika Anda menulis perpustakaan umum. Namun itu cara yang sangat mudah untuk meningkatkan kemanjuran diri ketika Anda bekerja di situs web atau aplikasi node.js.
sumber
Hanya solusi cepat dan kotor yang selalu saya gunakan. Saya tidak akan menyentuh prototipe, sama seperti praktik yang baik. Tentu saja, ada banyak cara untuk membuat ini lebih baik, tetapi Anda mendapatkan idenya.
sumber
[]
selalu mengembalikan array baru, itu setara dengannew Array()
tetapi dijamin untuk mengembalikan array karenaArray
bisa ditimpa oleh pengguna sedangkan[]
tidak bisa. Jadi ini adalah cara yang aman untuk mendapatkan prototipeArray
, kemudian seperti yang dijelaskan,call
digunakan untuk menjalankan fungsi pada nodelist seperti array (ini).sumber
[]
sebenarnya akan selalu mengembalikan array, sementarawindow.Array
dapat ditimpa dengan apa pun (di semua browser lama), demikian juga dapatwindow.Array.prototype.forEach
ditimpa dengan apa pun. Tidak ada jaminan keselamatan dalam kedua kasus ini, di browser yang tidak mendukung getter / setter atau penyegelan / pembekuan objek (pembekuan menyebabkan masalah ekstensibilitasnya sendiri).prototype
atau metode itu:forEach
.Norguard menjelaskan APA yang
[].forEach.call()
dilakukan dan James Allardice MENGAPA kita melakukannya: karena querySelectorAll mengembalikan aNodeList
yang tidak memiliki metode forEach ...Kecuali Anda memiliki browser modern seperti Chrome 51+, Firefox 50+, Opera 38, Safari 10.
Jika tidak, Anda dapat menambahkan Polyfill :
sumber
Banyak info bagus di halaman ini (lihat answer + answer + comment ), tetapi saya baru-baru ini memiliki pertanyaan yang sama dengan OP, dan butuh beberapa penggalian untuk mendapatkan gambaran keseluruhan. Jadi, inilah versi singkatnya:
Tujuannya adalah menggunakan
Array
metode pada arrayNodeList
yang tidak memiliki metode itu sendiri.Pola yang lebih lama mengkooptasi metode Array melalui
Function.call()
, dan menggunakan array literal ([]
) daripadaArray.prototype
karena lebih pendek untuk mengetik:Pola yang lebih baru (post ECMAScript 2015) akan digunakan
Array.from()
:sumber