Mengapa JavaScript tidak memiliki metode terakhir? [Tutup]

124

Agak aneh bahwa kelas JavaScript Array tidak menawarkan metode terakhir untuk mengambil elemen terakhir dari sebuah array. Saya tahu solusinya sederhana (Ar [Ar.length-1]), tetapi, tetap saja, ini terlalu sering digunakan.

Adakah alasan serius mengapa ini belum dimasukkan?

Nikhil Garg
sumber
39
Untuk kasus-kasus di mana Anda tidak keberatan mengubah array sebagai efek samping (mis. Di mana array hanya bersifat sementara), idiomnya adalah item= array.pop();.
bobince
7
Berikut ini adalah tolok ukur kinerja untuk banyak metode yang disebutkan: jsperf.com/get-last-item-from-array
Web_Designer
5
Astaga, setelah melihat halaman perf, tampaknya array[array.length-1]adalah cara yang lebih cepat dari yang lain.
Jondlm
@JondIm tetapi jika Anda membuat array dalam fungsinya, Anda perlu menemukan nama lokal untuk itu (yang mengarah ke nama seperti arr2), dan Anda memiliki 2 baris kode alih-alih oneliner
Danubian Sailor
1
(Ar[Ar.length-1])mendapat kinerja 20x lebih baik untuk saya.
Evgeni Sergeev

Jawaban:

38

Karena Javascript berubah sangat lambat. Dan itu karena orang memperbarui browser secara perlahan.

Banyak perpustakaan Javascript mengimplementasikan last()fungsinya sendiri . Gunakan satu!

Triptych
sumber
20
Paling tidak, Anda mungkin ingin mempertimbangkan menyarankan perpustakaan yang akan menyediakan implementasi. Misalnya, Underscore.js adalah pilihan yang baik. Lihat documentcloud.github.com/underscore/#ast
Sean Lynch
11
@Sean - Saya pikir saya akan tetap keluar dari bisnis merekomendasikan perpustakaan Javascript tertentu ke poster asli. Google melakukan pekerjaan yang cukup baik untuk menilai pendapat kolektif web tentang perpustakaan mana yang akan digunakan. Mengapa saya menyarankan yang khusus? Memang, mengapa Anda merekomendasikan underscore.js, yang tampaknya sangat enak bagi saya pada pandangan pertama?
Triptych
6
Saya sebenarnya lebih suka jawaban di bawah ini menerapkan fungsi di luar perpustakaan. Yang mengatakan, sebagai seseorang yang menemukan pertanyaan ini melalui Google, saya menyarankan bahwa jawaban teratas membantu orang lain melanjutkan pencarian mereka untuk solusi daripada mengirim mereka ke tombol kembali.
Sean Lynch
5
Pertanyaannya adalah "Mengapa fitur ini tidak dibangun ke dalam Javascript" bukan "Bagaimana bisa mencapai fungsi ini". Tidak ada alasan untuk berpikir penulis asli sedang mencari cara untuk benar-benar menulis last()fungsinya sendiri . Pertanyaannya adalah tentang sifat pengembangan bahasa inti Javascript itu sendiri.
Triptych
3
Tetapi jika @ Nikhil ingin tahu bagaimana mengimplementasikannya - garis bawah memiliki sumber yang sangat beranotasi. Implementasi last () ini cukup kuat, mungkin lebih dari itu diperlukan oleh penulis ini tetapi bagus untuk perpustakaan. documentcloud.github.com/underscore/docs/…
recbot
264

Anda dapat melakukan sesuatu seperti ini:

[10, 20, 30, 40].slice(-1)[0]

Jumlah metode pembantu yang dapat ditambahkan ke bahasa tidak terbatas. Saya kira mereka belum mempertimbangkan untuk menambahkan yang ini.

Álvaro González
sumber
11
tergoda untuk downvote untuk "close to infinity"
Triptych
11
Mengapa? Anda bisa sedekat yang Anda inginkan, tanpa batas :)
Álvaro González
35
Yang ini harus menjadi jawabannya.
Giampaolo Rodolà
7
@UpTheCreek, karena Anda tidak perlu menyimpan array ke variabel.
rmobi
5
@ ÁlvaroG.Vicario Ini bagus untuk array referensi, tetapi dalam contoh Anda Anda bekerja dengan angka. Sesuai MDN doc: "slice menyalin string dan angka ke dalam array baru. Perubahan pada string atau angka dalam satu array tidak memengaruhi array lainnya." Jika pengembang ingin mendapatkan referensi "array.last" untuk melakukan sesuatu dengan nilai elemen terakhir dalam array aslinya, dan nilai array kebetulan berupa string atau angka literal, metode ini tidak akan berfungsi.
1nfiniti
82

Mudah mendefinisikannya sendiri. Itulah kekuatan JavaScript.

if(!Array.prototype.last) {
    Array.prototype.last = function() {
        return this[this.length - 1];
    }
}

var arr = [1, 2, 5];
arr.last(); // 5

Namun, ini dapat menyebabkan masalah dengan kode pihak ke-3 yang (salah) gunakan for..in loop untuk beralih lebih dari array.

Namun, jika Anda tidak terikat dengan masalah dukungan browser , maka menggunakan sintaks ES5 baru untuk mendefinisikan properti dapat menyelesaikan masalah itu, dengan membuat fungsi tersebut tidak dapat dihitung, seperti:

Object.defineProperty(Array.prototype, 'last', {
    enumerable: false,
    configurable: true,
    get: function() {
        return this[this.length - 1];
    },
    set: undefined
});

var arr = [1, 2, 5];
arr.last; // 5
Anurag
sumber
11
perhatikan bahwa menambahkan properti ke prototipe Array dapat memecahkan kode di mana for..in digunakan untuk beralih pada array. Menggunakan for..in untuk mengulangi array adalah praktik yang buruk, tetapi hal itu dilakukan cukup umum sehingga mengubah prototipe Array juga merupakan praktik yang buruk. Secara umum, prototipe Object, Array, String, Number, Boolean, dan Date tidak boleh diubah jika skrip Anda perlu bekerja dengan kode lain yang tidak dikenal.
Dagg Nabbit
7
@ tidak - Terima kasih atas tipnya. Saya seharusnya menyebutkan bahwa alasan untuk menambahkan sintaks ES5 dengan enumerability yang disetel ke false adalah tepatnya untuk menyelesaikan for..inmasalah. Tentu, kami belum ada di sana dengan implementasi ES5 yang luas, tetapi cukup baik untuk tahu sekarang karena browser mengejar dengan cepat, termasuk IE9.
Anurag
4
Untuk daftar kosong, this.length - 1evaluasikan ke -1, yang, karena merupakan angka negatif, diperlakukan sebagai properti array, bukan indeks elemen.
claymation
26

i = [].concat(loves).pop(); //corn

ikon kucing suka popcorn

Silviu-Marian
sumber
15
Peringatan: ini membuat salinan seluruh daftar hanya untuk memunculkan satu elemen. Berpotensi sangat boros baik dalam waktu maupun ruang. Jangan lakukan itu.
Triptych
13

Opsi lain, terutama jika Anda sudah menggunakan UnderscoreJS, adalah:

_.last([1, 2, 3, 4]); // Will return 4
Pablo Diaz
sumber
5
Array.prototype.last = Array.prototype.last || function() {
    var l = this.length;
    return this[l-1];
}

x = [1,2];
alert( x.last() )
meder omuraliev
sumber
Apa yang harus menjadi output yang sesuai untuk [] .last ()? nullatau undefined?
Álvaro González
1
mungkin tidak terdefinisi untuk tetap konsisten dalam hal bahasa.
meder omuraliev
null Saya pikir - karena Anda memiliki array yang didefinisikan dengan baik - hanya saja tidak ada objek yang valid di dalamnya. undefined harus digunakan hanya ketika 'properti' terakhir tidak didefinisikan pada wadah yang disebut.
Nikhil Garg
3
kembali saja this[l-1]akan memberi Anda undefinedseperti biasa untuk mengakses properti yang tidak ada. Secara pribadi saya lebih suka JS melemparkan pengecualian daripada kembali undefined, tetapi JS lebih suka menyapu kesalahan di bawah karpet.
bobince
4

Datang ke sini mencari jawaban untuk pertanyaan ini sendiri. Jawaban irisan mungkin yang terbaik, tetapi saya pergi ke depan dan menciptakan fungsi "terakhir" hanya untuk berlatih memperluas prototipe, jadi saya pikir saya akan maju dan membagikannya. Ini memiliki manfaat tambahan dibandingkan yang lain sehingga Anda dapat secara opsional menghitung mundur melalui array, dan menarik, katakanlah, item kedua ke terakhir atau ketiga ke item terakhir. Jika Anda tidak menentukan jumlah, maka itu hanya default ke 1 dan mengeluarkan item terakhir.

Array.prototype.last = Array.prototype.last || function(count) {
    count = count || 1;
    var length = this.length;
    if (count <= length) {
        return this[length - count];
    } else {
        return null;
    }
};

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.last(); // returns 9
arr.last(4); // returns 6
arr.last(9); // returns 1
arr.last(10); // returns null
Daniel
sumber
Saat Anda menggunakan last(4)atau last(9)kehilangan arti nama fungsi, yaitu; last
Prashanth Shyamprasad
3

Berikut ini cara lain yang lebih sederhana untuk mengiris elemen terakhir

 var tags = [1, 2, 3, "foo", "bar", "foobar", "barfoo"];
 var lastObj = tags.slice(-1);

lastObj sekarang ["barfoo"] .

Python melakukan ini dengan cara yang sama dan ketika saya mencoba menggunakan JS itu berhasil. Saya menduga manipulasi string dalam bahasa scripting bekerja dengan cara yang sama.

Demikian pula, jika Anda ingin dua objek terakhir dalam array,

var lastTwoObj = tags.slice(-2)

akan memberi Anda ["foobar", "barfoo"]dan sebagainya.

Prashant
sumber
@ Jakub Terima kasih atas hasil editnya. Saya melewatkan tanda negatif yang sangat penting.
Prashant
Tidak, lastObjakan mengandung ["barfoo"]. Dalam hal apa pun, mengapa saya harus melakukan hal yang Array.prototype.slice.call(tagsadil tags.slice?
2

pop()Metode akan memunculkan nilai terakhir. Tetapi masalahnya adalah Anda akan kehilangan nilai terakhir dalam array

Prashanth Shyamprasad
sumber
-1

Ya, atau hanya:

var arr = [1, 2, 5];
arr.reverse()[0]

jika Anda menginginkan nilainya, dan bukan daftar baru.

TDahl
sumber
10
Tidak yakin, tetapi ini tampaknya cukup lambat
Jonathan Azulay
3
Selain lambat, ia juga memiliki efek samping yang buruk karena array aslinya dibalik.
Stephen Quan