Saya telah mengamati ini di Firefox-3.5.7 / Firebug-1.5.3 dan Firefox-3.6.16 / Firebug-1.6.2
Ketika saya menyalakan Firebug:
var x = new Array(3)
console.log(x)
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y)
// [undefined, undefined, undefined]
console.log( x.constructor == y.constructor) // true
console.log(
x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
y.map(function() { return 0; })
)
// [0, 0, 0]
Apa yang terjadi di sini? Apakah ini bug, atau saya salah paham cara menggunakan new Array(3)
?
javascript
arrays
map-function
rampion
sumber
sumber
var y = x.map(function(){return 0; });
, dan saya mendapatkan ini untuk kedua metode Array () baru dan array literal. Saya menguji di Firefox 4 dan Chrome.Jawaban:
Tampaknya contoh pertama
Membuat array dengan pointer yang tidak ditentukan.
Dan yang kedua membuat array dengan pointer ke 3 objek yang tidak terdefinisi, dalam hal ini pointer mereka sendiri tidak terdefinisi, hanya objek yang mereka tuju.
Karena peta dijalankan dalam konteks objek dalam array, saya yakin peta pertama gagal menjalankan fungsinya sama sekali sedangkan yang kedua berhasil dijalankan.
sumber
map
memanggil fungsi callback yang disediakan satu kali untuk setiap elemen dalam array, secara berurutan, dan membangun array baru dari hasilnya. Hanyacallback
dipanggil untuk indeks array yang telah menetapkan nilai ; tidak dipanggil untuk indeks yang telah dihapus atau yang tidak pernah diberi nilai. " Dalam hal ini,x
nilai-nilai belum secara eksplisit menetapkan nilai, sedangkan nilaiy
diberikan, meskipun itu adalah nilainyaundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
kecuali jikahasOwnProperty
dirinya sendiri memiliki bug:(new Array(1)).hasOwnProperty(0) === false
dan[undefined].hasOwnProperty(0) === true
. Bahkan, Anda dapat melakukan hal yang persis sama denganin
:0 in [undefined] === true
dan0 in new Array(0) === false
.x = new Array(3);
sama denganx = [,,,];
, tidakx = [undefined, undefined, undefined]
.Saya punya tugas yang saya hanya tahu panjang array dan perlu mengubah item. Saya ingin melakukan sesuatu seperti ini:
Untuk dengan cepat membuat array seperti ini:
Tapi itu tidak berhasil karena: (lihat jawaban Jonathan Lonowski beberapa jawaban di atas)
Solusinya bisa dengan mengisi item array dengan nilai apa pun (bahkan dengan tidak terdefinisi) menggunakan Array.prototype.fill ()
Tampilkan cuplikan kode
Memperbarui
Solusi lain dapat:
sumber
undefined
dalam.fill()
metode ini, menyederhanakan kode sangat sedikit untuklet arr = new Array(10).fill().map((val,idx) => idx);
Array.from(Array(10))
Dengan ES6, Anda dapat melakukannya
[...Array(10)].map((a, b) => a)
, cepat dan mudah!sumber
new Array(10).fill()
. Hasil yang sama seperti[...Array(10)]
[...Array(10).keys()]
Solusi ES6:
Tidak bekerja pada naskah (2.3), meskipun
sumber
Array(10).fill("").map( ...
adalah apa yang bekerja untuk saya dengan Script 2.9Array berbeda. Perbedaannya adalah bahwa
new Array(3)
menciptakan sebuah array dengan panjang tiga tetapi tanpa properti, sementara[undefined, undefined, undefined]
menciptakan array dengan panjang tiga dan tiga properti yang disebut "0", "1" dan "2", masing-masing dengan nilaiundefined
. Anda dapat melihat perbedaan menggunakanin
operator:Ini berasal dari fakta yang sedikit membingungkan bahwa jika Anda mencoba untuk mendapatkan nilai properti yang tidak ada dari objek asli apa pun di JavaScript, ia mengembalikan
undefined
(daripada melempar kesalahan, seperti yang terjadi ketika Anda mencoba merujuk ke variabel yang tidak ada) ), yang sama dengan apa yang Anda dapatkan jika properti sebelumnya secara eksplisit diatur keundefined
.sumber
Dari halaman MDC untuk
map
:[undefined]
sebenarnya menerapkan setter pada indeks (es) sehinggamap
akan mengulangi, sedangkannew Array(1)
hanya menginisialisasi indeks (es) dengan nilai defaultundefined
sehinggamap
melewatkannya.Saya percaya ini sama untuk semua metode iterasi .
sumber
Dalam spesifikasi edisi 6 ECMAScript.
new Array(3)
hanya mendefinisikan propertilength
dan tidak mendefinisikan seperti properti indeks{length: 3}
. lihat https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len Langkah 9.[undefined, undefined, undefined]
akan mendefinisikan properti indeks dan panjang properti seperti{0: undefined, 1: undefined, 2: undefined, length: 3}
. lihat https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
Langkah 5.metode
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
Array akan memeriksa properti index olehHasProperty
metode internal, sehingganew Array(3).map(v => 1)
tidak akan meminta panggilan balik itu.untuk detail lebih lanjut, lihat https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
Bagaimana cara memperbaiki?
sumber
Saya pikir cara terbaik untuk menjelaskan ini adalah dengan melihat cara Chrome menanganinya.
Jadi apa yang sebenarnya terjadi adalah bahwa Array baru () mengembalikan array kosong yang memiliki panjang 3, tetapi tidak ada nilai. Oleh karena itu, ketika Anda menjalankan
x.map
pada teknis array kosong, tidak ada yang harus ditetapkan.Firefox hanya 'mengisi' slot-slot kosong
undefined
itu walaupun tidak memiliki nilai.Saya tidak berpikir ini adalah bug, hanya cara yang buruk untuk mewakili apa yang sedang terjadi. Saya kira Chrome "lebih benar" karena ini menunjukkan bahwa sebenarnya tidak ada apa pun dalam array.
sumber
Baru saja berlari ke ini. Tentu akan nyaman untuk dapat menggunakan
Array(n).map
.Array(3)
hasil kira-kira{length: 3}
[undefined, undefined, undefined]
menciptakan sifat bernomor:{0: undefined, 1: undefined, 2: undefined, length: 3}
.Implementasi map () hanya bekerja pada properti yang didefinisikan.
sumber
Bukan bug. Begitulah konstruktor Array didefinisikan untuk bekerja.
Dari MDC:
The
.map()
Metode hanya mencakup pada iterasi elemen dari array yang telah secara eksplisit memiliki nilai-nilai yang ditetapkan. Bahkan penugasan eksplisitundefined
akan menyebabkan nilai dianggap memenuhi syarat untuk dimasukkan dalam iterasi. Tampaknya aneh, tetapi pada dasarnya perbedaan antaraundefined
properti eksplisit pada objek dan properti yang hilang:Objek
x
tidak memiliki properti yang disebut "z", dan objeky
tidak. Namun, dalam kedua kasus itu tampak bahwa "nilai" properti ituundefined
. Dalam sebuah array, situasinya mirip: nilailength
apakah secara implisit melakukan penugasan nilai ke semua elemen dari nol hinggalength - 1
. The.map()
Fungsi karena itu tidak akan melakukan apa-apa (tidak akan memanggil callback) saat dipanggil pada sebuah array baru dibangun dengan konstruktor Array dan argumen numerik.sumber
undefined
untuk selamanya?x = []
sebagai gantinyax = new Array()
Jika Anda melakukan ini untuk mengisi array dengan nilai dengan mudah, tidak dapat menggunakan fill untuk alasan dukungan browser dan benar-benar tidak ingin melakukan for-loop, Anda juga dapat melakukan
x = new Array(3).join(".").split(".").map(...
yang akan memberi Anda array kosong string.Cukup jelek yang harus saya katakan, tetapi setidaknya masalah dan niat dikomunikasikan dengan jelas.
sumber
Karena pertanyaannya adalah mengapa, ini berkaitan dengan bagaimana JS dirancang.
Ada 2 alasan utama yang bisa saya pikirkan untuk menjelaskan perilaku ini:
Kinerja: Diberikan
x = 10000
dannew Array(x)
bijaksana bagi konstruktor untuk menghindari perulangan dari 0 hingga 10.000 untuk mengisi array denganundefined
nilai.Secara implisit "tidak terdefinisi": Memberi
a = [undefined, undefined]
danb = new Array(2)
,a[1]
danb[1]
keduanya akan kembaliundefined
, tetapia[8]
danb[8]
juga akan kembaliundefined
meskipun mereka berada di luar jangkauan.Pada akhirnya, notasi
empty x 3
adalah jalan pintas untuk menghindari pengaturan dan menampilkan daftar panjangundefined
nilai yangundefined
tetap karena mereka tidak dinyatakan secara eksplisit.Catatan: Array yang diberikan
a = [0]
dana[9] = 9
,console.log(a)
akan kembali(10) [0, empty x 8, 9]
, mengisi celah secara otomatis dengan mengembalikan perbedaan antara dua nilai yang dinyatakan secara eksplisit.sumber
Untuk alasan yang dijelaskan dalam jawaban lain,
Array(n).map
tidak berfungsi. Namun, dalam ES2015Array.from
menerima fungsi peta:sumber
Inilah metode utilitas sederhana sebagai solusinya:
MapFor sederhana
Contoh Lengkap
Berikut adalah contoh yang lebih lengkap (dengan pemeriksaan kewarasan) yang juga memungkinkan menentukan indeks awal opsional:
Menghitung mundur
Memanipulasi indeks yang diteruskan ke panggilan balik memungkinkan penghitungan mundur:
sumber