Perché JavaScript non ha un ultimo metodo? [chiuso]


124

È un po 'strano che la classe di array JavaScript non offra un ultimo metodo per recuperare l'ultimo elemento di un array. So che la soluzione è semplice (Ar [Ar.length-1]), ma, tuttavia, viene utilizzata troppo spesso.

Qualche motivo serio per cui questo non è stato ancora incorporato?


39
Per i casi in cui non ti dispiace alterare l'array come un effetto collaterale (cioè dove l'array è comunque solo temporaneo), il linguaggio sarebbe item= array.pop();.
Bobince,

7
Ecco un benchmark delle prestazioni per molti dei metodi citati: jsperf.com/get-last-item-from-array
Web_Designer

5
Buon cielo, dopo aver guardato quella pagina perf, sembra che array[array.length-1]sia molto più veloce degli altri.
Jondlm,

@JondIm ma se crei un array in funzione, devi inventare il nome locale per esso (che porta a nomi come arr2) e hai 2 righe di codice invece di oneliner
Danubian Sailor

1
(Ar[Ar.length-1])ottiene prestazioni 20 volte migliori per me.
Evgeni Sergeev,

Risposte:


38

Perché Javascript cambia molto lentamente. E questo perché le persone aggiornano i browser lentamente.

Molte librerie Javascript implementano la propria last()funzione. Usane uno!


20
Per lo meno, potresti prendere in considerazione l'idea di suggerire una libreria che fornisca l'implementazione. Ad esempio, Underscore.js è una buona scelta. Vedi documentcloud.github.com/underscore/#last
Sean Lynch il

11
@Sean - Pensavo che sarei rimasto fuori dagli affari di raccomandare una particolare libreria Javascript al poster originale. Google fa un ottimo lavoro nel valutare l'opinione collettiva del web su quale libreria utilizzare. Perché dovrei suggerirne uno in particolare? In effetti, perché mi hai consigliato underscore.js, che a prima vista mi sembra molto gustoso?
Trittico

6
In realtà preferisco la risposta di seguito dell'implementazione della funzione al di fuori di una libreria. Detto questo, come qualcuno che si è imbattuto in questa domanda tramite Google, stavo suggerendo che la risposta migliore aiuta gli altri a continuare la loro ricerca di una soluzione piuttosto che inviarli al pulsante Indietro.
Sean Lynch,

5
La domanda era "Perché questa funzionalità non è integrata in Javascript" e non "Come si può ottenere questa funzionalità". Non c'è motivo di pensare che l'autore originale stesse cercando come scrivere effettivamente la propria last()funzione. La domanda riguardava la natura dello sviluppo del linguaggio principale di Javascript stesso.
Trittico

3
Ma se @Nikhil vuole sapere come implementarlo, il carattere di sottolineatura ha una meravigliosa fonte annotata. Questa implementazione di last () è abbastanza robusta, probabilmente più di questo è necessaria per questo autore, ma ottima per una libreria. documentcloud.github.com/underscore/docs/…
reconbot

264

Puoi fare qualcosa del genere:

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

La quantità di metodi di supporto che è possibile aggiungere a una lingua è infinita. Suppongo che non abbiano preso in considerazione l'aggiunta di questo.


11
tentato di sottovalutare "vicino all'infinito"
Trittico,

11
Perché? Puoi avvicinarti quanto vuoi, nessun limite :)
Álvaro González,

35
Questa dovrebbe essere la risposta.
Giampaolo Rodolà,

7
@UpTheCreek, perché non è necessario archiviare l'array in una variabile.
rmobis,

5
@ ÁlvaroG.Vicario Va bene per una serie di riferimenti, ma nel tuo esempio stai lavorando con i numeri. Secondo il documento MDN: "slice copia stringhe e numeri nel nuovo array. Le modifiche alla stringa o al numero in un array non influiscono sull'altro array." Se lo sviluppatore desidera ottenere un riferimento "array.last" per fare qualcosa con il valore dell'ultimo elemento nella loro matrice originale, e i valori della matrice risultano essere stringhe o numeri letterali, questo metodo non funzionerà.
1nfiniti

82

È facile definirne uno da soli. Questo è il potere di JavaScript.

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

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

Tuttavia, ciò può causare problemi con il codice di terze parti che (erroneamente) utilizza i for..inloop per scorrere su array.

Tuttavia, se non si è vincolati a problemi di supporto del browser , l'utilizzo della nuova sintassi ES5 per definire le proprietà può risolvere il problema, rendendo la funzione non enumerabile, in questo modo:

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

11
si noti che l'aggiunta di proprietà al prototipo di array può interrompere il codice in cui for..in viene utilizzato per scorrere su un array. L'uso di for..in per eseguire l'iterazione di un array è una cattiva pratica, ma è abbastanza comune che alterare il prototipo di Array è anche una cattiva pratica. In generale, i prototipi di Object, Array, String, Number, Boolean e Date non devono essere modificati se lo script deve funzionare con altri codici sconosciuti.
Dagg Nabbit,

7
@no - Grazie per il suggerimento. Avrei dovuto menzionare che la ragione per aggiungere la sintassi ES5 con l'enumerabilità impostata su false era proprio per risolvere il for..inproblema. Certo, non siamo ancora lì con una vasta implementazione di ES5, ma è abbastanza buono da sapere ora poiché i browser lo stanno recuperando velocemente, incluso IE9.
Anurag,

4
Per gli elenchi vuoti, viene this.length - 1valutato come -1, poiché è un numero negativo, viene trattato come una proprietà dell'array, non come un indice di elemento.
Claymation,

26

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

icona gatto ama i popcorn


15
Attenzione: questo crea una copia dell'intero elenco solo per far apparire un elemento. Potenzialmente molto dispendioso sia nel tempo che nello spazio. Non farlo
Trittico

13

Un'altra opzione, specialmente se stai già utilizzando UnderscoreJS, sarebbe:

_.last([1, 2, 3, 4]); // Will return 4

5
Array.prototype.last = Array.prototype.last || function() {
    var l = this.length;
    return this[l-1];
}

x = [1,2];
alert( x.last() )

Quale dovrebbe essere l'output appropriato per [] .last ()? nullo undefined?
Álvaro González,

1
probabilmente indefinito per mantenerlo coerente dal punto di vista linguistico.
meder omuraliev il

null Penso, perché hai un array ben definito, solo che non ci sono oggetti validi in esso. undefined dovrebbe essere usato solo quando l'ultima 'proprietà' non è definita sul contenitore chiamato.
Nikhil Garg,

3
solo tornare this[l-1]ti darebbe undefinedcome è normale per l'accesso a proprietà inesistenti. Personalmente preferirei che JS lanciasse un'eccezione piuttosto che tornare undefined, ma JS preferisce spazzare gli errori sotto il tappeto.
Bobince,

4

Sono venuto qui alla ricerca di una risposta a questa domanda. La risposta alla fetta è probabilmente la migliore, ma sono andato avanti e ho creato una funzione "ultima" solo per esercitarmi ad estendere i prototipi, quindi ho pensato di andare avanti e condividerla. Ha il vantaggio aggiuntivo rispetto ad alcuni altri di farti facoltativamente contare all'indietro attraverso l'array e di estrarre, diciamo, il secondo all'ultimo o il terzo all'ultimo elemento. Se non specifichi un conteggio, il valore predefinito è 1 ed estrae l'ultimo elemento.

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

Quando usi last(4)o last(9)perdi il significato del nome della funzione, ovvero; last
Prashanth Shyamprasad,

3

Ecco un altro modo più semplice per tagliare gli ultimi elementi

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

lastObjè adesso ["barfoo"].

Python lo fa allo stesso modo e quando ho provato a usare JS ha funzionato. Immagino che la manipolazione delle stringhe nei linguaggi di scripting funzioni allo stesso modo.

Allo stesso modo, se vuoi gli ultimi due oggetti in un array,

var lastTwoObj = tags.slice(-2)

ti darà ["foobar", "barfoo"]e così via.


@Jakub Grazie per la modifica. Ho perso il segno negativo cruciale.
Prashant,

No, lastObjconterrà ["barfoo"]. In ogni caso, perché dovrei fare Array.prototype.slice.call(tagsinvece di solo tags.slice?


-1

Sì, o semplicemente:

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

se si desidera il valore e non un nuovo elenco.


10
Non sono sicuro, ma questo sembra piuttosto lento
Jonathan Azulay l'

3
Oltre ad essere lento, ha anche un brutto effetto collaterale in quanto l'array originale è invertito.
Stephen Quan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.