¿Por qué JavaScript no tiene un último método? [cerrado]

124

Es un poco extraño que la clase JavaScript Array no ofrezca un último método para recuperar el último elemento de una matriz. Sé que la solución es simple (Ar [Ar.length-1]), pero aún así, esto se usa con demasiada frecuencia.

¿Alguna razón seria por la cual esto aún no está incorporado?

Nikhil Garg
fuente
39
Para los casos en los que no le importa alterar la matriz como un efecto secundario (es decir, donde la matriz es solo temporal de todos modos), el idioma sería item= array.pop();.
bobince
77
Aquí hay un punto de referencia de rendimiento para muchos de los métodos mencionados: jsperf.com/get-last-item-from-array
Web_Designer
55
Dios mío, después de mirar esa página de presentación, parece que array[array.length-1]es mucho más rápido que los demás.
Jondlm
@JondIm, pero si crea una matriz en función, debe inventar un nombre local para ella (lo que lleva a nombres como arr2), y tiene 2 líneas de código en lugar de oneliner
Danubian Sailor
1
(Ar[Ar.length-1])obtiene 20 veces mejor rendimiento para mí.
Evgeni Sergeev

Respuestas:

38

Porque Javascript cambia muy lentamente. Y eso es porque la gente actualiza los navegadores lentamente.

Muchas bibliotecas Javascript implementan su propia last()función. Use uno!

Tríptico
fuente
20
Como mínimo, puede considerar sugerir una biblioteca que proporcione la implementación. Por ejemplo, Underscore.js es una buena opción. Ver documentcloud.github.com/underscore/#last
Sean Lynch
11
@Sean: pensé que me mantendría fuera del negocio de recomendar una biblioteca Javascript particular al póster original. Google hace un muy buen trabajo al evaluar la opinión colectiva de la web sobre qué biblioteca utilizar. ¿Por qué sugeriría uno en particular? De hecho, ¿por qué me has recomendado underscore.js, que a primera vista me parece muy sabrosa?
Tríptico
66
De hecho, prefiero la respuesta a continuación de implementar la función fuera de una biblioteca. Dicho esto, como alguien que tropezó con esta pregunta a través de Google, estaba sugiriendo que la respuesta principal ayudara a otros a continuar su búsqueda de una solución en lugar de enviarlos al botón Atrás.
Sean Lynch
55
La pregunta era "¿Por qué esta función no está integrada en Javascript?", No "¿Cómo se puede lograr esta funcionalidad?". No hay razón para pensar que el autor original estaba buscando cómo escribir realmente su propia last()función. La pregunta se refería a la naturaleza del desarrollo del lenguaje central Javascript mismo.
Tríptico
3
Pero si @Nikhil quiere saber cómo implementarlo, el subrayado tiene una maravillosa fuente anotada. Esta implementación de last () es bastante robusta, probablemente más de la que necesita este autor pero excelente para una biblioteca. documentcloud.github.com/underscore/docs/…
reconbot
264

Puedes hacer algo como esto:

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

La cantidad de métodos auxiliares que se pueden agregar a un idioma es infinita. Supongo que simplemente no han considerado agregar este.

Álvaro González
fuente
11
tentado a votar a favor de "cerca del infinito"
Tríptico
11
¿Por qué? Puedes acercarte lo que quieras, sin límite :)
Álvaro González
35
Esta debería ser la respuesta.
Giampaolo Rodolà
77
@UpTheCreek, porque no necesita almacenar la matriz en una variable.
rmobis
55
@ ÁlvaroG.Vicario Esto está bien para una variedad de referencias, pero en tu ejemplo estás trabajando con números. Según el documento de MDN: "el segmento copia cadenas y números en la nueva matriz. Los cambios en la cadena o el número en una matriz no afectan a la otra matriz". Si el desarrollador desea obtener una referencia "array.last" para hacer algo con el valor del último elemento en su matriz original, y los valores de la matriz son literales de cadena o número, este método no funcionará.
1nfiniti
82

Es fácil definir uno usted mismo. Ese es el poder de JavaScript.

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

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

Sin embargo, esto puede causar problemas con el código de terceros que (incorrectamente) usa for..inbucles para iterar sobre las matrices.

Sin embargo, si no está vinculado con problemas de soporte del navegador , el uso de la nueva sintaxis de ES5 para definir propiedades puede resolver ese problema, haciendo que la función no sea enumerable, de la siguiente manera:

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
fuente
11
tenga en cuenta que agregar propiedades al prototipo de Array puede romper el código donde for..in se usa para iterar sobre una matriz. Usar for..in para iterar una matriz es una mala práctica, pero se hace con tanta frecuencia que alterar el prototipo de Array también es una mala práctica. En general, los prototipos de Object, Array, String, Number, Boolean y Date no deben modificarse si su script necesita trabajar con otro código desconocido.
Dagg Nabbit
77
@no - Gracias por el consejo. Debería haber mencionado que la razón para agregar la sintaxis ES5 con la enumeración establecida en falso fue precisamente para resolver el for..inproblema. Claro, todavía no estamos allí con una implementación amplia de ES5, pero es lo suficientemente bueno como para saber ahora, ya que los navegadores se están poniendo al día rápidamente, incluido IE9.
Anurag
44
Para listas vacías, this.length - 1evalúa a -1, que, debido a que es un número negativo, se trata como una propiedad de matriz, no como un índice de elemento.
claymation
26

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

gato icono ama las palomitas de maíz

Silviu-Marian
fuente
15
Advertencia: esto crea una copia de toda la lista solo para hacer estallar un elemento. Potencialmente muy derrochador tanto en tiempo como en espacio. No lo hagas
Tríptico
13

Otra opción, especialmente si ya está utilizando UnderscoreJS, sería:

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

x = [1,2];
alert( x.last() )
meder omuraliev
fuente
¿Cuál debería ser la salida adecuada para [] .last ()? nullo undefined?
Álvaro González
1
probablemente indefinido para mantenerlo consistente en el lenguaje.
meder omuraliev
nulo, creo, porque tienes una matriz bien definida, solo que no hay objetos válidos en ella. undefined debe usarse solo cuando la última 'propiedad' no está definida en el contenedor llamado.
Nikhil Garg
3
solo regresar this[l-1]le daría, undefinedcomo es normal, el acceso a propiedades inexistentes. Personalmente prefiero que JS haya lanzado una excepción en lugar de regresar undefined, pero JS prefiere barrer los errores debajo de la alfombra.
bobince
4

Vine aquí buscando una respuesta a esta pregunta yo mismo. La respuesta de corte es probablemente la mejor, pero seguí adelante y creé una "última" función solo para practicar la extensión de prototipos, así que pensé en seguir adelante y compartirla. Tiene el beneficio adicional sobre algunos otros de permitirle contar opcionalmente hacia atrás a través de la matriz y extraer, por ejemplo, el penúltimo elemento o el penúltimo elemento. Si no especifica un recuento, el valor predeterminado es 1 y extrae el último 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
Daniel
fuente
Cuando usa last(4)o last(9)pierde el significado del nombre de la función, es decir; last
Prashanth Shyamprasad
3

Aquí hay otra forma más simple de cortar los últimos elementos.

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

lastObjes ahora ["barfoo"].

Python hace esto de la misma manera y cuando intenté usar JS funcionó. Supongo que la manipulación de cadenas en lenguajes de script funciona de la misma manera.

Del mismo modo, si desea los dos últimos objetos en una matriz,

var lastTwoObj = tags.slice(-2)

te dará ["foobar", "barfoo"]y así sucesivamente.

Prasante
fuente
@Jakub Gracias por la edición. Perdí el signo negativo crucial.
Prashant
No, lastObjlo contendré ["barfoo"]. En cualquier caso, ¿por qué debería hacerlo en Array.prototype.slice.call(tagslugar de solo tags.slice?
2

pop()El método mostrará el último valor. Pero el problema es que perderá el último valor de la matriz.

Prashanth Shyamprasad
fuente
-1

Si, o solo:

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

si quieres el valor, y no una nueva lista.

TDahl
fuente
10
No estoy seguro, pero esto parece bastante lento
Jonathan Azulay
3
Además de ser lento, también tiene un efecto secundario desagradable en que se invierte la matriz original.
Stephen Quan