Pourquoi JavaScript n'a-t-il pas une dernière méthode? [fermé]

124

C'est un peu bizarre que la classe JavaScript Array n'offre pas une dernière méthode pour récupérer le dernier élément d'un tableau. Je sais que la solution est simple (Ar [Ar.length-1]), mais, encore, c'est trop fréquemment utilisé.

Y a-t-il des raisons sérieuses pour lesquelles cela n'est pas encore intégré?

Nikhil Garg
la source
39
Pour les cas où cela ne vous dérange pas de modifier le tableau comme un effet secondaire (c'est-à-dire où le tableau n'est de toute façon que temporaire), l'idiome serait item= array.pop();.
bobince
7
Voici un benchmark de performance pour la plupart des méthodes mentionnées: jsperf.com/get-last-item-from-array
Web_Designer
5
Bon Dieu, après avoir regardé cette page de perf, il semble que array[array.length-1]c'est beaucoup plus rapide que les autres.
Jondlm
@JondIm mais si vous créez un tableau dans function, vous devez inventer son nom local (qui mène à des noms tels que arr2), et vous avez 2 lignes de code au lieu de oneliner
Danubian Sailor
1
(Ar[Ar.length-1])obtient des performances 20 fois meilleures pour moi.
Evgeni Sergeev

Réponses:

38

Parce que Javascript change très lentement. Et c'est parce que les gens mettent à jour lentement les navigateurs.

De nombreuses bibliothèques Javascript implémentent leur propre last()fonction. Utilisez-en un!

Triptyque
la source
20
À tout le moins, vous voudrez peut-être envisager de suggérer une bibliothèque qui fournirait l'implémentation. Par exemple, Underscore.js est un bon choix. Voir documentcloud.github.com/underscore/#last
Sean Lynch
11
@Sean - Je pensais que je ne recommanderais pas une bibliothèque Javascript particulière à l'affiche originale. Google évalue assez bien l'opinion collective du Web sur la bibliothèque à utiliser. Pourquoi en suggérerais-je un en particulier? En effet, pourquoi avez-vous recommandé underscore.js, qui me semble très savoureux du mois à première vue?
Triptyque du
6
Je préfère en fait la réponse ci-dessous pour implémenter la fonction en dehors d'une bibliothèque. Cela dit, en tant que personne qui est tombée sur cette question via Google, je suggérais que la réponse supérieure aide les autres à poursuivre leur recherche d'une solution plutôt que de les envoyer au bouton retour.
Sean Lynch
5
La question était "Pourquoi cette fonctionnalité n'est-elle pas intégrée à Javascript?" Et non "Comment réaliser cette fonctionnalité". Il n'y a aucune raison de penser que l'auteur original cherchait comment écrire sa propre last()fonction. La question portait sur la nature du développement du langage de base Javascript lui-même.
Triptyque du
3
Mais si @Nikhil veut savoir comment l'implémenter, le soulignement a une merveilleuse source annotée. Cette implémentation de last () est assez robuste, probablement plus que nécessaire par cet auteur mais idéale pour une bibliothèque. documentcloud.github.com/underscore/docs/…
reconbot
264

Vous pouvez faire quelque chose comme ceci:

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

La quantité de méthodes d'assistance pouvant être ajoutées à un langage est infinie. Je suppose qu'ils n'ont tout simplement pas envisagé d'ajouter celui-ci.

Álvaro González
la source
11
tenté de voter contre "près de l'infini"
Triptyque
11
Pourquoi? Vous pouvez vous approcher aussi près que vous le souhaitez, sans limite :)
Álvaro González
35
Celui-ci devrait être la réponse.
Giampaolo Rodolà
7
@UpTheCreek, car vous n'avez pas besoin de stocker le tableau dans une variable.
rmobis
5
@ ÁlvaroG.Vicario C'est parfait pour un tableau de références, mais dans votre exemple, vous travaillez avec des nombres. Selon le document MDN: "slice copie les chaînes et les nombres dans le nouveau tableau. Les modifications apportées à la chaîne ou au nombre dans un tableau n'affectent pas l'autre tableau." Si le développeur veut obtenir une référence "array.last" afin de faire quelque chose avec la valeur du dernier élément dans leur tableau d'origine, et que les valeurs du tableau se trouvent être des chaînes ou des nombres littéraux, cette méthode ne fonctionnera pas.
1nfiniti
82

Il est facile d'en définir un vous-même. C'est la puissance de JavaScript.

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

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

Cependant, cela peut causer des problèmes avec le code tiers qui utilise (à tort) des for..inboucles pour itérer sur des tableaux.

Cependant, si vous n'êtes pas lié par des problèmes de prise en charge du navigateur , l'utilisation de la nouvelle syntaxe ES5 pour définir les propriétés peut résoudre ce problème, en rendant la fonction non énumérable, comme ceci:

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
la source
11
notez que l'ajout de propriétés au prototype de Array peut casser le code où for..in est utilisé pour itérer sur un tableau. Utiliser for..in pour itérer un tableau est une mauvaise pratique, mais c'est assez souvent fait pour que modifier le prototype d'Array soit également une mauvaise pratique. En général, les prototypes d'Object, Array, String, Number, Boolean et Date ne doivent pas être modifiés si votre script doit fonctionner avec un autre code inconnu.
Dagg Nabbit
7
@no - Merci pour le tuyau. J'aurais dû mentionner que la raison de l'ajout de la syntaxe ES5 avec l'énumérabilité définie sur false était précisément de résoudre le for..inproblème. Bien sûr, nous n'en sommes pas encore là avec une large implémentation d'ES5, mais c'est assez bon pour le savoir maintenant, car les navigateurs le rattrapent rapidement, y compris IE9.
Anurag
4
Pour les listes vides, this.length - 1évalue à -1, qui, car il s'agit d'un nombre négatif, est traité comme une propriété de tableau et non comme un index d'élément.
claymation
26

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

icône de chat aime le pop-corn

Silviu-Marian
la source
15
Attention: cela crée une copie de la liste entière juste pour faire apparaître un élément. Potentiellement très gaspilleur en temps et en espace. Ne fais pas ça.
Triptyque du
13

Une autre option, surtout si vous utilisez déjà UnderscoreJS, serait:

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

x = [1,2];
alert( x.last() )
meder omuraliev
la source
Quelle devrait être la sortie appropriée pour [] .last ()? nullou undefined?
Álvaro González
1
probablement indéfini pour le garder cohérent en termes de langage.
meder omuraliev
null Je pense - parce que vous avez un tableau bien défini - juste qu'il n'y a pas d'objets valides dedans. undefined ne doit être utilisé que lorsque la dernière 'propriété' n'est pas définie sur le conteneur appelé.
Nikhil Garg
3
retourner simplement this[l-1]vous donnerait undefinedcomme d'habitude pour accéder à des propriétés inexistantes. Personnellement, je préfère que JS lève une exception plutôt que de revenir undefined, mais JS préfère balayer les erreurs sous le tapis.
bobince
4

Je suis venu ici à la recherche d'une réponse à cette question moi-même. La réponse par tranche est probablement la meilleure, mais je suis allé de l'avant et j'ai créé une "dernière" fonction juste pour m'entraîner à étendre les prototypes, alors j'ai pensé que j'allais la partager. Il présente l'avantage supplémentaire par rapport à certains autres de vous permettre de compter à rebours dans le tableau et de retirer, par exemple, l'avant-dernier ou le troisième au dernier élément. Si vous ne spécifiez pas de décompte, la valeur par défaut est 1 et extrait le dernier élément.

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
la source
Lorsque vous utilisez last(4)ou que last(9)vous perdez la signification du nom de la fonction, c'est-à-dire; last
Prashanth Shyamprasad
3

Voici une autre façon plus simple de découper les derniers éléments

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

lastObjest maintenant ["barfoo"].

Python fait cela de la même manière et quand j'ai essayé d'utiliser JS, cela a fonctionné. Je suppose que la manipulation de chaînes dans les langages de script fonctionne de la même manière.

De même, si vous voulez que les deux derniers objets d'un tableau,

var lastTwoObj = tags.slice(-2)

vous donnera ["foobar", "barfoo"]et ainsi de suite.

Prashant
la source
@Jakub Merci pour la modification. J'ai raté le signe négatif crucial.
Prashant
Non, lastObjcontiendra ["barfoo"]. Dans tous les cas, pourquoi ferais-je Array.prototype.slice.call(tagsplutôt que juste tags.slice?
2

pop()La méthode sortira la dernière valeur. Mais le problème est que vous perdrez la dernière valeur du tableau

Prashanth Shyamprasad
la source
-1

Ouais, ou juste:

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

si vous voulez la valeur, et non une nouvelle liste.

TDahl
la source
10
Pas sûr, mais cela semble assez lent
Jonathan Azulay
3
En plus d'être lent, il a également un effet secondaire désagréable en ce que le tableau d'origine est inversé.
Stephen Quan