เหตุใด JavaScript จึงไม่มีวิธีสุดท้าย [ปิด]


124

เป็นเรื่องแปลกที่คลาส JavaScript Array ไม่มีวิธีสุดท้ายในการดึงข้อมูลองค์ประกอบสุดท้ายของอาร์เรย์ ฉันรู้ว่าวิธีแก้ปัญหานั้นง่าย (Ar [Ar.length-1]) แต่ก็ยังใช้บ่อยเกินไป

สาเหตุที่ร้ายแรงใด ๆ ที่ยังไม่รวมเข้าด้วยกัน?


39
สำหรับกรณีที่คุณไม่ทราบการเปลี่ยนแปลงอาร์เรย์เป็นผลข้างเคียง (เช่น. ที่อาร์เรย์เป็นเพียงชั่วคราวอยู่แล้ว) item= array.pop();สำนวนจะเป็น
bobince

7
นี่คือเกณฑ์มาตรฐานประสิทธิภาพสำหรับหลาย ๆ วิธีที่กล่าวถึง: jsperf.com/get-last-item-from-array
Web_Designer

5
สวรรค์ที่ดีหลังจากที่กำลังมองหาที่หน้า perf ที่จะปรากฏarray[array.length-1]เป็นวิธีที่เร็วกว่าคนอื่น ๆ
Jondlm

@JondIm แต่ถ้าคุณสร้างอาร์เรย์ในฟังก์ชันคุณจะต้องสร้างชื่อท้องถิ่นสำหรับมัน (ซึ่งนำไปสู่ชื่อเช่น arr2) และคุณมีโค้ด 2 บรรทัดแทน oneliner
Danubian Sailor

1
(Ar[Ar.length-1])ได้รับประสิทธิภาพที่ดีขึ้น 20 เท่าสำหรับฉัน
Evgeni Sergeev

คำตอบ:


38

เนื่องจาก Javascript เปลี่ยนแปลงช้ามาก และนั่นเป็นเพราะผู้คนอัปเกรดเบราว์เซอร์ช้า

ไลบรารี Javascript จำนวนมากใช้last()ฟังก์ชันของตนเอง ใช้อันเดียว!


20
อย่างน้อยที่สุดคุณอาจต้องการพิจารณาแนะนำไลบรารีที่สามารถนำไปใช้งานได้ ตัวอย่างเช่น Underscore.js เป็นตัวเลือกที่ดี ดูdocumentcloud.github.com/underscore/#last
Sean Lynch

11
@Sean - ฉันคิดว่าฉันจะไม่ทำธุรกิจในการแนะนำไลบรารี Javascript โดยเฉพาะให้กับโปสเตอร์ต้นฉบับ Google ทำงานได้ดีในการประเมินความคิดเห็นโดยรวมของเว็บว่าควรใช้ไลบรารีใด เหตุใดฉันจึงแนะนำรายการใดรายการหนึ่ง ทำไมคุณถึงแนะนำ underscore.js ซึ่งดูเหมือนจะเป็นรสชาติของเดือนสำหรับฉันในตอนแรก?
Triptych

6
ฉันชอบคำตอบด้านล่างของการใช้ฟังก์ชันภายนอกไลบรารี ที่กล่าวว่าในฐานะคนที่สะดุดกับคำถามนี้ผ่าน Google ฉันขอแนะนำว่าคำตอบยอดนิยมช่วยให้ผู้อื่นค้นหาวิธีแก้ปัญหาต่อไปแทนที่จะส่งไปที่ปุ่มย้อนกลับ
Sean Lynch

5
คำถามคือ "เหตุใดจึงไม่สร้างคุณลักษณะนี้ใน Javascript" ไม่ใช่ "จะบรรลุฟังก์ชันนี้ได้อย่างไร" ไม่มีเหตุผลที่จะคิดว่าผู้เขียนต้นฉบับกำลังมองหาวิธีการเขียนlast()ฟังก์ชันของตัวเองจริงๆ คำถามเกี่ยวกับธรรมชาติของการพัฒนาภาษาหลักของ Javascript เอง
Triptych

3
แต่ถ้า @Nikhil ต้องการทราบวิธีการใช้งาน - ขีดล่างมีแหล่งข้อมูลประกอบที่ยอดเยี่ยม การใช้งาน last () นี้ค่อนข้างมีประสิทธิภาพอาจเป็นที่ต้องการของผู้เขียนคนนี้มากกว่า แต่เหมาะสำหรับห้องสมุด documentcloud.github.com/underscore/docs/…
reconbot

264

คุณสามารถทำสิ่งนี้:

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

จำนวนวิธีการช่วยเหลือที่สามารถเพิ่มลงในภาษานั้นไม่มีที่สิ้นสุด ฉันคิดว่าพวกเขาไม่ได้พิจารณาเพิ่มอันนี้


11
อยากให้โหวต "close to infinity"
Triptych

11
ทำไม? คุณสามารถเข้าใกล้ได้เท่าที่คุณต้องการไม่มีขีด จำกัด :)
ÁlvaroGonzález

35
อันนี้น่าจะตอบโจทย์
Giampaolo Rodolà

7
@UpTheCreek เพราะคุณไม่จำเป็นต้องเก็บอาร์เรย์ไว้ในตัวแปร
rmobis

5
@ ÁlvaroG.Vicarioนี่ใช้ได้ดีสำหรับการอ้างอิงที่หลากหลาย แต่ในตัวอย่างของคุณคุณกำลังทำงานกับตัวเลข ตามเอกสาร MDN: "slice คัดลอกสตริงและตัวเลขลงในอาร์เรย์ใหม่การเปลี่ยนแปลงสตริงหรือตัวเลขในอาร์เรย์หนึ่งจะไม่มีผลกับอาร์เรย์อื่น" หากนักพัฒนาต้องการรับข้อมูลอ้างอิง "array.last" เพื่อทำบางสิ่งกับค่าขององค์ประกอบสุดท้ายในอาร์เรย์เดิมและค่าอาร์เรย์เป็นสตริงหรือตัวเลขตามตัวอักษรวิธีนี้จะใช้ไม่ได้
1nfiniti

82

เป็นเรื่องง่ายที่จะกำหนดด้วยตัวคุณเอง นั่นคือพลังของ JavaScript

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

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

อย่างไรก็ตามสิ่งนี้อาจทำให้เกิดปัญหากับรหัสของบุคคลที่สามซึ่ง (ไม่ถูกต้อง) ใช้for..inลูปเพื่อวนซ้ำบนอาร์เรย์

อย่างไรก็ตามหากคุณไม่ได้ผูกพันกับปัญหาการสนับสนุนเบราว์เซอร์การใช้ไวยากรณ์ ES5 ใหม่เพื่อกำหนดคุณสมบัติสามารถแก้ปัญหานั้นได้โดยทำให้ฟังก์ชันไม่สามารถนับได้ดังนี้:

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 สามารถทำลายโค้ดโดยที่ for..in ถูกใช้เพื่อทำซ้ำบนอาร์เรย์ การใช้ for.. ในการทำซ้ำอาร์เรย์ถือเป็นการปฏิบัติที่ไม่ดี แต่โดยทั่วไปแล้วการเปลี่ยนต้นแบบของ Array ก็เพียงพอแล้วเช่นกัน โดยทั่วไปไม่ควรเปลี่ยนแปลงต้นแบบของ Object, Array, String, Number, Boolean และ Date หากสคริปต์ของคุณต้องทำงานกับโค้ดอื่น ๆ ที่ไม่รู้จัก
Dagg Nabbit

7
@no - ขอบคุณสำหรับเคล็ดลับ ฉันควรจะได้กล่าวว่าเหตุผลสำหรับการเพิ่มไวยากรณ์ ES5 กับชุด enumerability เท็จได้อย่างแม่นยำในการแก้for..inปัญหา แน่นอนว่าเรายังไม่ได้ใช้งาน ES5 ในวงกว้าง แต่ก็ดีพอที่จะรู้ว่าตอนนี้เบราว์เซอร์กำลังตามมาอย่างรวดเร็วรวมถึง IE9 ด้วย
Anurag

4
สำหรับรายการว่างให้this.length - 1ประเมินเป็น-1ซึ่งเนื่องจากเป็นจำนวนลบจึงถือว่าเป็นคุณสมบัติอาร์เรย์ไม่ใช่ดัชนีองค์ประกอบ
claymation

26

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

ไอคอนแมวชอบข้าวโพดคั่ว


15
คำเตือน: สิ่งนี้จะสร้างสำเนาของรายการทั้งหมดเพื่อแสดงองค์ประกอบเดียว อาจเป็นการสิ้นเปลืองทั้งเวลาและพื้นที่ อย่าทำ
Triptych


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

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

ผลลัพธ์ที่เหมาะสมสำหรับ [] .last () ควรเป็นอย่างไร nullหรือundefined?
ÁlvaroGonzález

1
อาจไม่ได้กำหนดไว้เพื่อให้สอดคล้องกับภาษาที่ชาญฉลาด
meder omuraliev

null ฉันคิดว่า - เพราะคุณมีอาร์เรย์ที่กำหนดไว้อย่างดีเพียงแค่ว่าไม่มีวัตถุที่ถูกต้องอยู่ในนั้น ควรใช้ไม่ได้กำหนดก็ต่อเมื่อไม่ได้กำหนด 'คุณสมบัติ' สุดท้ายบนคอนเทนเนอร์ที่เรียกว่า
Nikhil Garg

3
เพียงแค่กลับมาthis[l-1]จะทำให้คุณundefinedเข้าถึงคุณสมบัติที่ไม่มีอยู่จริงได้ตามปกติ โดยส่วนตัวแล้วฉันอยากให้ JS โยนข้อยกเว้นมากกว่าที่จะกลับมาundefinedแต่ JS ชอบที่จะกวาดข้อผิดพลาดใต้พรม
bobince

4

มาที่นี่เพื่อหาคำตอบสำหรับคำถามนี้ด้วยตัวเอง คำตอบของ Slice น่าจะดีที่สุด แต่ฉันได้สร้างฟังก์ชัน "สุดท้าย" เพียงเพื่อฝึกฝนการขยายต้นแบบดังนั้นฉันจึงคิดว่าจะแบ่งปันต่อไป มีประโยชน์เพิ่มเติมเหนือข้ออื่น ๆ ในการให้คุณสามารถเลือกนับย้อนหลังผ่านอาร์เรย์และดึงรายการที่สองเป็นรายการสุดท้ายหรือรายการที่สามออกจากรายการสุดท้าย หากคุณไม่ระบุการนับก็จะใช้ค่าเริ่มต้นเป็น 1 และดึงรายการสุดท้ายออกมา

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

เมื่อคุณใช้last(4)หรือlast(9)คุณสูญเสียความหมายของชื่อฟังก์ชันเช่น; last
Prashanth Shyamprasad

3

นี่เป็นอีกวิธีหนึ่งที่ง่ายกว่าในการแบ่งองค์ประกอบสุดท้าย

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

lastObj["barfoo"]อยู่ในขณะนี้

Python ทำแบบเดียวกันและเมื่อฉันลองใช้ JS มันก็ได้ผล ฉันเดาว่าการปรับแต่งสตริงในภาษาสคริปต์ทำงานในลักษณะเดียวกัน

ในทำนองเดียวกันถ้าคุณต้องการสองวัตถุสุดท้ายในอาร์เรย์

var lastTwoObj = tags.slice(-2)

จะให้คุณ["foobar", "barfoo"]และอื่น ๆ


@Jakub ขอบคุณสำหรับการแก้ไข ฉันพลาดเครื่องหมายเชิงลบที่สำคัญ
Prashant

ไม่มีจะมีlastObj ["barfoo"]ไม่ว่าในกรณีใดทำไมฉันต้องทำArray.prototype.slice.call(tagsแทนที่จะเป็นเพียงแค่tags.slice?


-1

ใช่หรือเพียงแค่:

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

หากคุณต้องการค่าไม่ใช่รายการใหม่


10
ไม่แน่ใจ แต่ดูเหมือนว่าจะค่อนข้างช้า
Jonathan Azulay

3
นอกเหนือจากความช้าแล้วยังมีผลข้างเคียงที่น่ารังเกียจเนื่องจากอาร์เรย์เดิมจะกลับรายการ
Stephen Quan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.