JavaScript'in neden son bir yöntemi yok? [kapalı]


124

JavaScript Array sınıfının bir dizinin son öğesini almak için son bir yöntem sunmaması biraz garip. Çözümün basit olduğunu biliyorum (Ar [Ar.length-1]), ancak yine de bu çok sık kullanılıyor.

Bunun henüz dahil edilmemesinin ciddi bir nedeni var mı?


39
Diziyi bir yan etki olarak değiştirmenin sakıncası olmadığı durumlarda (yani dizinin zaten sadece geçici olduğu durumlarda), deyim olacaktır item= array.pop();.
bobince

7
İşte bahsedilen yöntemlerin birçoğu için performans kriter var: jsperf.com/get-last-item-from-array
Web_Designer

5
Yüce tanrım, o perf sayfasına bakarak sonra, göründüğü array[array.length-1]olan yolu diğerlerinden daha hızlı.
Jondlm

@JondIm, ancak işlevde bir dizi oluşturursanız, bunun için yerel ad icat etmeniz gerekir (bu da arr2 gibi adlara götürür) ve oneliner yerine 2 satır kodunuz olur
Danubian Sailor

1
(Ar[Ar.length-1])benim için 20 kat daha iyi performans elde ediyor.
Evgeni Sergeev

Yanıtlar:


38

Çünkü Javascript çok yavaş değişiyor. Bunun nedeni, insanların tarayıcıları yavaşça yükseltmeleridir.

Çoğu Javascript kitaplığı kendi last()işlevini uygular . Birini kullanın!


20
En azından, uygulamayı sağlayacak bir kitaplık önermeyi düşünebilirsiniz. Örneğin, Underscore.js iyi bir seçimdir. Bkz documentcloud.github.com/underscore/#last
Sean Lynch

11
@Sean - Orijinal postere belirli bir Javascript kitaplığını tavsiye etme işinin dışında kalacağımı düşündüm. Google, web'in hangi kitaplığın kullanılacağına ilişkin toplu görüşünü değerlendirmek konusunda oldukça iyi bir iş çıkarmaktadır. Neden belirli birini önereyim? Gerçekten de, neden ilk bakışta bana ayın lezzeti gibi görünen undercore.js'yi önerdiniz?
Triptych

6
Aslında işlevi bir kütüphane dışında uygulamak için aşağıdaki cevabı tercih ediyorum. Bununla birlikte, Google aracılığıyla bu soruya rastlayan biri olarak, en iyi cevabın, geri düğmesine göndermek yerine başkalarının bir çözüm aramaya devam etmesine yardımcı olmasını öneriyordum.
Sean Lynch

5
Soru, "Bu özellik neden Javascript'te yerleşik değil", "Bu işlevselliğe nasıl ulaşılır" idi. Orijinal yazarın kendi last()işlevini gerçekten nasıl yazacağını aradığını düşünmek için hiçbir neden yok . Soru, Javascript çekirdek dilinin gelişiminin doğasıyla ilgiliydi.
Triptych

3
Ancak @Nikhil bunu nasıl uygulayacağını öğrenmek istiyorsa - alt çizgi harika bir açıklamalı kaynağa sahiptir. Last () işlevinin bu uygulaması oldukça sağlamdır, muhtemelen bu yazar tarafından daha fazlasına ihtiyaç duyulmaktadır, ancak bir kitaplık için harikadır. documentcloud.github.com/underscore/docs/…
reconbot

264

Bunun gibi bir şey yapabilirsiniz:

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

Bir dile eklenebilecek yardımcı yöntemlerin miktarı sonsuzdur. Sanırım bunu eklemeyi düşünmediler.


11
"sonsuza yakın" için olumsuz oy kullanma isteği
Triptych

11
Neden? İstediğiniz kadar yaklaşabilirsiniz, sınırsız :)
Álvaro González

35
Cevap bu olmalı.
Giampaolo Rodolà

7
@UpTheCreek, çünkü diziyi bir değişkene kaydetmeniz gerekmiyor.
rmobis

5
@ ÁlvaroG.Vicario Bu bir dizi referans için uygundur, ancak örneğinizde sayılarla çalışıyorsunuz. MDN belgesine göre: "dilim, dizeleri ve sayıları yeni diziye kopyalar. Bir dizideki dize veya sayıdaki değişiklikler diğer diziyi etkilemez." Geliştirici, orijinal dizisindeki son öğenin değeriyle bir şeyler yapmak için bir "dizi.last" başvurusu almak isterse ve dizi değerleri dize veya sayı değişmezleri olursa, bu yöntem çalışmayacaktır.
1nfiniti

82

Birini kendiniz tanımlamak kolaydır. JavaScript'in gücü budur.

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

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

Ancak bu, for..indizileri yinelemek için (yanlış bir şekilde) döngüler kullanan 3. taraf kodunda sorunlara neden olabilir .

Bununla birlikte, tarayıcı desteği sorunlarına bağlı değilseniz, özellikleri tanımlamak için yeni ES5 sözdizimini kullanmak , işlevi numaralandırılamaz hale getirerek bu sorunu çözebilir, örneğin:

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
Array'in prototipine özellik eklemenin, bir dizi üzerinde yineleme yapmak için for..in kullanıldığında kodu bozabileceğini unutmayın. Bir diziyi yinelemek için for..in kullanmak kötü bir uygulamadır, ancak Array'in prototipini değiştirmenin de kötü bir uygulama olduğu yeterince yaygın olarak yapılır. Genel olarak, komut dosyanızın diğer bilinmeyen kodlarla çalışması gerekiyorsa, Object, Array, String, Number, Boolean ve Date prototipleri değiştirilmemelidir.
Dagg Nabbit

7
@no - İpucu için teşekkürler. ES5 sözdizimini, numaralandırılabilirlik false olarak ayarlanmış şekilde eklemenin nedeninin tam olarak sorunu çözmek olduğunu söylemeliydim for..in. Elbette, ES5'in geniş bir uygulamasıyla henüz orada değiliz, ancak tarayıcılar IE9 da dahil olmak üzere onu hızlı bir şekilde yakaladığından şimdi bilmek yeterince iyi.
Anurag

4
Boş listeler this.length - 1için -1, negatif bir sayı olduğu için bir öğe dizini olarak değil, bir dizi özelliği olarak değerlendirilen , olarak değerlendirilir .
claymation

26

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

simge kedi patlamış mısır sever


15
Uyarı: Bu, yalnızca bir öğeyi açmak için tüm listenin bir kopyasını oluşturur. Hem zamanda hem de mekanda potansiyel olarak çok israf. Yapma.
Triptych

13

Başka bir seçenek, özellikle de UnderscoreJS kullanıyorsanız, şunlar olacaktır:

_.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() )

[] .Last () için uygun çıktı ne olmalıdır? nullveya undefined?
Álvaro González

1
dil açısından tutarlı olması için muhtemelen tanımsız.
meder omuraliev

null Bence - çünkü iyi tanımlanmış bir diziniz var - sadece içinde geçerli nesneler yok. undefined, yalnızca son 'özellik' çağrılan kapta tanımlanmadığında kullanılmalıdır.
Nikhil Garg

3
sadece geri dönmek this[l-1], undefinedvar olmayan mülklere erişmeniz için normal olduğu gibi verir . Şahsen undefined, JS'nin geri dönmek yerine bir istisna atmasını tercih ederim , ancak JS hataları halının altına süpürmeyi tercih ediyor.
bobince

4

Buraya bu sorunun cevabını kendim aramak için geldim. Dilim cevabı muhtemelen en iyisidir, ancak devam ettim ve sadece prototipleri genişletmek için "son" bir işlev yarattım, bu yüzden devam edip paylaşacağımı düşündüm. İsteğe bağlı olarak dizi boyunca geriye doğru saymanıza ve örneğin ikinciden sondan üçüncü veya üçüncüye kadar çekmenize izin veren diğer bazılarına göre ek bir faydası vardır. Bir sayı belirtmezseniz, varsayılan olarak 1 olur ve son öğeyi çıkarır.

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

Fonksiyon adını kullandığınızda last(4)veya last(9)anlamını kaybettiğinizde, yani; last
Prashanth Shyamprasad

3

İşte son elemanları dilimlemenin daha basit bir yolu

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

lastObjşimdi ["barfoo"].

Python bunu aynı şekilde yapıyor ve JS'yi kullanmayı denediğimde işe yaradı. Komut dosyası dillerinde dize manipülasyonunun da aynı şekilde çalıştığını tahmin ediyorum.

Benzer şekilde, bir dizideki son iki nesneyi istiyorsanız,

var lastTwoObj = tags.slice(-2)

sana verecek ["foobar", "barfoo"]ve benzeri.


@Jakub Düzenleme için teşekkürler. Önemli negatif işareti kaçırdım.
Prashant

Hayır, lastObjiçerecek ["barfoo"]. Her durumda, neden Array.prototype.slice.call(tagssadece yerine yapayım tags.slice?


-1

Evet veya sadece:

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

Değeri ve yeni bir liste istemiyorsanız.


10
Emin değilim, ama bu oldukça yavaş görünüyor
Jonathan Azulay

3
Yavaş olmasının yanı sıra, orijinal dizinin tersine çevrilmesi gibi kötü bir yan etkiye de sahiptir.
Stephen Quan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.