Tại sao JavaScript không có phương thức cuối cùng? [đóng cửa]


124

Thật kỳ lạ khi lớp JavaScript Array không cung cấp một phương thức cuối cùng để lấy phần tử cuối cùng của một mảng. Tôi biết giải pháp rất đơn giản (Ar [Ar.length-1]), nhưng, vẫn còn, điều này quá thường xuyên được sử dụng.

Bất kỳ lý do nghiêm trọng tại sao điều này chưa được kết hợp?


39
Đối với trường hợp bạn không ngại thay đổi mảng thành hiệu ứng phụ (nghĩa là trong đó mảng chỉ là tạm thời), thì thành ngữ sẽ là item= array.pop();.
bobince

7
Đây là điểm chuẩn hiệu suất cho nhiều phương thức được đề cập: jsperf.com/get-last-item-from-array
Web_Designer

5
Trời ơi, sau khi xem xét rằng trang Perf, dường như array[array.length-1]cách nhanh hơn so với những người khác.
Jondlm

@JondIm nhưng nếu bạn tạo một mảng trong hàm, bạn cần phát minh ra tên địa phương cho nó (dẫn đến các tên như Array2) và bạn có 2 dòng mã thay vì oneliner
Danubian Sailor

1
(Ar[Ar.length-1])đạt hiệu suất tốt hơn gấp 20 lần đối với tôi.
Evgeni Sergeev

Câu trả lời:


38

Bởi vì Javascript thay đổi rất chậm. Và đó là vì mọi người nâng cấp trình duyệt chậm.

Nhiều thư viện Javascript thực hiện last()chức năng riêng của họ . Sử dụng một!


20
Ít nhất, bạn có thể muốn xem xét đề xuất một thư viện sẽ cung cấp việc thực hiện. Ví dụ, Underscore.js là một lựa chọn tốt. Xem documentcloud.github.com/underscore/#last
Sean Lynch

11
@Sean - Tôi nghĩ rằng tôi sẽ đứng ngoài công việc giới thiệu một thư viện Javascript cụ thể cho poster gốc. Google thực hiện khá tốt việc đánh giá ý kiến ​​tập thể của web về việc sử dụng thư viện nào. Tại sao tôi lại đề xuất một cái cụ thể? Thật vậy, tại sao bạn lại đề xuất underscore.js, có vẻ rất hợp với tôi ngay từ cái nhìn đầu tiên?
Triptych

6
Tôi thực sự thích câu trả lời dưới đây về việc thực hiện chức năng bên ngoài thư viện. Điều đó nói rằng, khi một người nào đó vấp phải câu hỏi này thông qua Google, tôi đã gợi ý rằng câu trả lời hàng đầu giúp người khác tiếp tục tìm kiếm giải pháp thay vì gửi chúng đến nút quay lại.
Sean Lynch

5
Câu hỏi là "Tại sao tính năng này không được tích hợp trong Javascript" chứ không phải "Làm thế nào có thể đạt được chức năng này". Không có lý do để nghĩ rằng tác giả ban đầu đang tìm cách làm thế nào để thực sự viết last()chức năng của mình . Câu hỏi là về bản chất của sự phát triển ngôn ngữ cốt lõi Javascript.
Triptych

3
Nhưng nếu @Nikhil muốn biết cách triển khai nó - gạch dưới có một nguồn chú thích tuyệt vời. Việc triển khai Last () này khá mạnh mẽ, có lẽ cần nhiều hơn nữa bởi tác giả này nhưng tuyệt vời cho một thư viện. documentcloud.github.com/underscore/docs/ từ
recbot

264

Bạn có thể làm một cái gì đó như thế này:

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

Số lượng phương thức trợ giúp có thể được thêm vào một ngôn ngữ là vô hạn. Tôi cho rằng họ chưa xem xét thêm cái này.


11
cám dỗ downvote cho "gần vô cùng"
Triptych

11
Tại sao? Bạn có thể đến gần như bạn muốn, không giới hạn :)
Álvaro González

35
Điều này nên là câu trả lời.
Giampaolo Rodolà

7
@UpTheCalet, vì bạn không cần lưu trữ mảng vào một biến.
rmobis

5
@ ÁlvaroG.Vicario Điều này tốt cho một loạt các tài liệu tham khảo, nhưng trong ví dụ của bạn, bạn đang làm việc với các con số. Theo tài liệu MDN: "lát sao chép chuỗi và số vào mảng mới. Thay đổi chuỗi hoặc số trong một mảng không ảnh hưởng đến mảng khác." Nếu nhà phát triển muốn lấy "Array.last" tham chiếu để thực hiện điều gì đó với giá trị của phần tử cuối cùng trong mảng ban đầu của chúng và các giá trị mảng xảy ra là chuỗi hoặc số bằng chữ, phương thức này sẽ không hoạt động.
1nfiniti

82

Thật dễ dàng để tự xác định một. Đó là sức mạnh của JavaScript.

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

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

Tuy nhiên, điều này có thể gây ra sự cố với mã của bên thứ 3 (không chính xác) sử dụng for..incác vòng lặp để lặp lại trên các mảng.

Tuy nhiên, nếu bạn không bị ràng buộc với các vấn đề hỗ trợ trình duyệt , thì sử dụng cú pháp ES5 mới để xác định các thuộc tính có thể giải quyết vấn đề đó, bằng cách làm cho hàm không thể đếm được, như vậy:

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
lưu ý rằng việc thêm thuộc tính vào nguyên mẫu của Array có thể phá vỡ mã trong đó for..in được sử dụng để lặp qua một mảng. Sử dụng for..in để lặp lại một mảng là một thực tiễn tồi, nhưng nó được thực hiện đủ phổ biến để thay đổi nguyên mẫu của Array cũng là một thực tiễn tồi. Nói chung, các nguyên mẫu của Object, Array, String, Number, Boolean và Date không nên bị thay đổi nếu tập lệnh của bạn cần hoạt động với mã không xác định khác.
Dagg Nợi

7
@no - Cảm ơn vì tiền boa. Tôi nên đề cập rằng lý do thêm cú pháp ES5 với vô số được đặt thành false chính xác là để giải quyết for..invấn đề. Chắc chắn, chúng ta chưa có triển khai ES5, nhưng đủ để biết bây giờ vì các trình duyệt đang bắt kịp nó nhanh chóng, bao gồm cả IE9.
Anurag

4
Đối với danh sách rỗng, this.length - 1đánh giá lại để -1, trong đó, bởi vì nó là một số âm, được coi là một tài sản mảng, không phải là một chỉ số phần tử.
đất sét

26

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

biểu tượng mèo yêu bỏng ngô


15
Cảnh báo: điều này tạo ra một bản sao của toàn bộ danh sách chỉ để bật một phần tử. Có khả năng rất lãng phí trong cả thời gian và không gian. Đừng làm điều đó.
Triptych

13

Một tùy chọn khác, đặc biệt là nếu bạn đã sử dụng UnderscoreJS, sẽ là:

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

Điều gì sẽ là đầu ra thích hợp cho [] .last ()? nullhay undefined?
Álvaro González

1
có lẽ không xác định để giữ cho nó phù hợp với ngôn ngữ
meder omuraliev

null tôi nghĩ - bởi vì bạn có một mảng được xác định rõ - chỉ là không có đối tượng hợp lệ trong đó. không xác định chỉ được sử dụng khi 'thuộc tính' cuối cùng không được xác định trên vùng chứa được gọi.
Nikhil Garg

3
chỉ trở về this[l-1]sẽ cung cấp cho bạn undefinednhư bình thường để truy cập các thuộc tính không tồn tại. Cá nhân tôi thà rằng JS đã ném một ngoại lệ thay vì quay lại undefined, nhưng JS thích quét các lỗi dưới tấm thảm.
bobince

4

Đến đây để tìm một câu trả lời cho câu hỏi này. Câu trả lời lát có lẽ là tốt nhất, nhưng tôi đã tiếp tục và tạo ra một chức năng "cuối cùng" chỉ để thực hành mở rộng các nguyên mẫu, vì vậy tôi nghĩ rằng tôi sẽ tiếp tục và chia sẻ nó. Nó có thêm lợi ích so với một số cái khác cho phép bạn tùy ý đếm ngược qua mảng và kéo ra, giả sử, thứ hai để cuối cùng hoặc thứ ba đến mục cuối cùng. Nếu bạn không chỉ định số đếm, nó chỉ mặc định là 1 và lấy ra mục cuối cùng.

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

Khi bạn sử dụng last(4)hoặc last(9)bạn mất ý nghĩa của tên hàm, nghĩa là; last
Prashanth Shyamprasad

3

Đây là một cách đơn giản hơn để cắt các phần tử cuối cùng

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

lastObjtại là ["barfoo"].

Python thực hiện điều này theo cách tương tự và khi tôi thử sử dụng JS, nó đã hoạt động. Tôi đoán thao tác chuỗi trong các ngôn ngữ kịch bản hoạt động theo cùng một cách.

Tương tự, nếu bạn muốn hai đối tượng cuối cùng trong một mảng,

var lastTwoObj = tags.slice(-2)

sẽ cung cấp cho bạn ["foobar", "barfoo"]và như vậy.


@Jakub Cảm ơn bạn đã chỉnh sửa. Tôi đã bỏ lỡ các dấu hiệu tiêu cực quan trọng.
Prashant

Không, lastObjsẽ chứa ["barfoo"]. Trong mọi trường hợp, tại sao tôi sẽ làm Array.prototype.slice.call(tagsthay vì chỉ tags.slice?

2

pop()phương pháp sẽ bật giá trị cuối cùng ra. Nhưng vấn đề là bạn sẽ mất giá trị cuối cùng trong mảng


-1

Vâng, hoặc chỉ:

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

nếu bạn muốn giá trị, và không phải là một danh sách mới.


10
Không chắc chắn, nhưng điều này có vẻ khá chậm
Jonathan Azulay

3
Ngoài việc bị chậm, nó còn có tác dụng phụ khó chịu ở chỗ mảng ban đầu bị đảo ngược.
Stephen Quan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.