Saya melihat kode dari Mozilla yang menambahkan metode filter ke Array dan ada sederet kode yang membingungkan saya.
var len = this.length >>> 0;
Saya belum pernah melihat >>> digunakan dalam JavaScript sebelumnya.
Apa itu dan apa fungsinya?
javascript
operators
bit-shift
Kenneth J
sumber
sumber
Array.prototype.push
/Array.prototype.pop
- hexmen.com/blog/2006/12/push-and-pop (meskipun ia melakukan tes, haha).Jawaban:
Itu tidak hanya mengkonversi non-Angka ke Angka, itu mengubahnya menjadi Angka yang dapat dinyatakan sebagai ints 32-bit unsigned.
Meskipun Nomor JavaScript ini adalah double-presisi mengapung (*), operator bitwise (
<<
,>>
,&
,|
dan~
) didefinisikan dalam hal operasi pada 32-bit bilangan bulat. Melakukan operasi bitwise mengubah angka menjadi int yang ditandatangani 32-bit, kehilangan pecahan dan bit tempat yang lebih tinggi dari 32, sebelum melakukan perhitungan dan kemudian mengonversi kembali ke Angka.Jadi melakukan operasi bitwise tanpa efek aktual, seperti pergeseran ke kanan 0 bit
>>0
, adalah cara cepat untuk membulatkan angka dan memastikannya berada dalam kisaran int 32-bit. Selain itu,>>>
operator rangkap tiga , setelah melakukan operasi yang tidak ditandatangani, mengubah hasil perhitungannya menjadi Angka sebagai bilangan bulat yang tidak ditandatangani daripada bilangan bulat yang ditandatangani yang lain, sehingga dapat digunakan untuk mengonversi negatif ke komplemen 32-bit-dua-dua-komplemen. versi sebagai Nomor besar. Menggunakan>>>0
memastikan Anda memiliki bilangan bulat antara 0 dan 0xFFFFFFFF.Dalam hal ini ini berguna karena ECMAScript mendefinisikan indeks Array dalam hal 32 bit int unsigned. Jadi, jika Anda mencoba menerapkan
array.filter
dengan cara yang persis duplikat apa yang dikatakan standar ECMAScript Fifth Edition, Anda akan memasukkan nomor ke int unsigned 32-bit seperti ini.(Pada kenyataannya ada sedikit kebutuhan praktis untuk ini karena mudah-mudahan orang tidak akan menetapkan
array.length
untuk0.5
,-1
,1e21
atau'LEMONS'
. Tapi ini penulis JavaScript kita bicarakan, sehingga Anda tidak pernah tahu ...)Ringkasan:
(*: yah, mereka didefinisikan berperilaku seperti pelampung. Tidak akan mengejutkan saya jika beberapa mesin JavaScript benar-benar menggunakan ints ketika itu bisa, karena alasan kinerja. Tapi itu akan menjadi detail implementasi yang tidak akan Anda ambil keuntungan dari.)
sumber
RangeError: invalid array length
.Array.prototype.filter.call
), jadiarray
mungkin tidak benar-benar nyataArray
: mungkin beberapa kelas lain yang ditentukan pengguna. (Sayangnya, itu tidak bisa diandalkan menjadi NodeList, yang mana ketika Anda benar-benar ingin melakukan itu, karena itu adalah objek host. Itu meninggalkan satu-satunya tempat Anda akan secara realistis melakukan itu sebagaiarguments
pseudo-Array.)if
pernyataan ini ketika mencoba mengidentifikasi bahwa sisi kiri evaluasi bukan int?'lemons'>>>0 === 0 && 0 >>>0 === 0
mengevaluasi sebagai benar? meskipun lemon jelas sebuah kata ..?Operator pergeseran kanan yang tidak ditandatangani digunakan dalam implementasi metode semua array ekstra Mozilla, untuk memastikan bahwa
length
properti adalah bilangan bulat 32-bit yang tidak ditandatangani .The
length
properti objek array dijelaskan dalam spesifikasi sebagai:Operator ini adalah cara terpendek untuk mencapainya, metode array internal menggunakan
ToUint32
operasi, tetapi metode itu tidak dapat diakses dan ada pada spesifikasi untuk tujuan implementasi.Implementasi ekstra array Mozilla mencoba untuk memenuhi ECMAScript 5 , lihat deskripsi
Array.prototype.indexOf
metode (§ 15.4.4.14):Seperti yang Anda lihat, mereka hanya ingin mereproduksi perilaku
ToUint32
metode untuk mematuhi spesifikasi ES5 pada implementasi ES3, dan seperti yang saya katakan sebelumnya, operator shift kanan yang tidak bertanda tangan adalah cara termudah.sumber
ToUint32
sepertinya ini tidak perlu bagiku.Array.prototype
metode sengaja generik , mereka dapat digunakan pada objek seperti array misalnyaArray.prototype.indexOf.call({0:'foo', 1:'bar', length: 2}, 'bar') == 1;
. Thearguments
objek juga merupakan contoh yang baik. Untuk objek array murni , tidak mungkin untuk mengubah jenislength
properti, karena mereka menerapkan metode internal [[Put
]] khusus, dan ketika tugas dibuat kelength
properti, sekali lagi dikonversiToUint32
dan tindakan lain diambil, seperti menghapus indeks di atas panjang baru ...Itu adalah operator bit shift kanan yang tidak ditandatangani . Perbedaan antara ini dan operator bit shift kanan yang ditandatangani , adalah bahwa operator shift bit kanan yang tidak ditandatangani ( >>> ) mengisi dengan nol dari kiri, dan operator bit shift kanan yang ditandatangani ( >> ) mengisi dengan bit tanda, dengan demikian mempertahankan tanda nilai numerik saat digeser.
sumber
>>>
dikonversi ke integer, yang+
tidak dilakukan unary .Driis telah cukup menjelaskan apa itu operator dan apa fungsinya. Inilah makna di baliknya / mengapa itu digunakan:
Menggeser ke mana pun dengan
0
cara mengembalikan nomor asli dan akan dilemparkannull
ke0
. Tampaknya kode contoh yang Anda lihat gunakanthis.length >>> 0
untuk memastikan bahwalen
itu numerik meskipunthis.length
tidak ditentukan.Bagi banyak orang, operasi bitwise tidak jelas (dan Douglas Crockford / jslint menyarankan agar tidak menggunakan hal-hal seperti itu). Itu tidak berarti bahwa itu salah untuk dilakukan, tetapi metode yang lebih menguntungkan dan akrab ada untuk membuat kode lebih mudah dibaca. Cara yang lebih jelas untuk memastikan bahwa
len
adalah0
merupakan salah satu dari dua metode berikut.atau
sumber
NaN
.. Eg+{}
... Ini mungkin yang terbaik untuk menggabungkan dua:+length||0
>>>
adalah operator shift kanan yang tidak ditandatangani ( lihat hal. 76 dari spesifikasi JavaScript 1.5 ), yang bertentangan dengan>>
, yang ditandatangani Operator shift kanan.>>>
mengubah hasil pergeseran angka negatif karena itu tidak mempertahankan bit tanda ketika menggeser . Konsekuensi dari ini dapat dipahami dengan contoh, dari seorang penafsir:Jadi apa yang mungkin dimaksudkan untuk dilakukan di sini adalah untuk mendapatkan panjang, atau 0 jika panjangnya tidak ditentukan atau bukan bilangan bulat, seperti
"cabbage"
contoh di atas. Saya pikir dalam kasus ini aman untuk berasumsi bahwa halthis.length
itu tidak akan pernah terjadi< 0
. Namun demikian, saya berpendapat bahwa contoh ini adalah hack jahat , karena dua alasan:Perilaku
<<<
ketika menggunakan angka negatif, efek samping mungkin tidak dimaksudkan (atau kemungkinan terjadi) pada contoh di atas.Maksud kode tidak jelas , karena keberadaan pertanyaan ini diverifikasi.
Praktik terbaik mungkin menggunakan sesuatu yang lebih mudah dibaca kecuali kinerja sangat penting:
sumber
-1 >>> 0
pernah terjadi dan jika demikian, apakah benar-benar diinginkan untuk mengubahnya ke 4294967295? Sepertinya ini akan menyebabkan loop berjalan beberapa kali lebih banyak dari yang diperlukan.this.length
tidak mungkin untuk tahu. Untuk setiap implementasi "waras" panjang string tidak boleh negatif, tetapi kemudian orang mungkin berpendapat bahwa dalam lingkungan "waras" kita dapat mengasumsikan keberadaanthis.length
properti yang selalu mengembalikan bilangan integral.Dua alasan:
Hasil >>> adalah "integral"
undefined >>> 0 = 0 (karena JS akan mencoba dan memaksa LFS ke konteks numerik, ini akan bekerja untuk "foo" >>> 0, dll. juga)
Ingat bahwa angka dalam JS memiliki representasi internal ganda. Ini hanya cara "cepat" input kewarasan dasar panjang.
Namun , -1 >>> 0 (oops, kemungkinan bukan panjang yang diinginkan!)
sumber
Contoh Kode Java di bawah ini menjelaskan dengan baik:
Outputnya adalah sebagai berikut:
sumber