2012-01-15 27 views
7

Tại saoGọi [] .reverse trên một chuỗi

[].reverse.call("string"); 

thất bại (lỗi trong cả Firefox và IE, trả về chuỗi gốc trong chrome) trong khi kêu gọi tất cả các phương pháp mảng khác trên một tác phẩm chuỗi?

>>> [].splice.call("string",3) 
["i", "n", "g"] 
>>> [].map.call("string",function (a) {return a +a;}) 
["ss", "tt", "rr", "ii", "nn", "gg"] 
+0

_ "tất cả các phương thức mảng khác" _ - hiện '.sort()' có hoạt động không? Đối với những người làm việc, họ có làm việc trong tất cả các trình duyệt không? (Tôi đoán chúng sẽ thất bại đối với các trình duyệt cũ hơn không thực hiện ký hiệu chỉ mục kiểu «[]' kiểu mảng cho chuỗi, mặc dù tôi chưa thử nghiệm nó.) – nnnnnn

+0

@nnnnnn sắp xếp không hoạt động cho cùng một lý do như vậy – Hai

+0

@Hai: FYI, '.splice()' không thực sự hoạt động. Chrome là loại, đủ để cung cấp cho bạn giá trị trả về, nhưng nếu bạn tham khảo chuỗi gốc trước khi nối nó, bạn sẽ thấy rằng nó không được sửa đổi. –

Trả lời

8

.reverse() sửa đổi một mảng và chuỗi không thay đổi.


Bạn có thể mượn Array.prototype.slice để chuyển đổi thành mảng, sau đó đảo ngược và tham gia.

var s = "string"; 

var s2 = [].slice.call(s).reverse().join(''); 

Chỉ cần lưu ý rằng trong các phiên bản cũ hơn của IE, bạn không thể thao tác chuỗi như mảng.

+1

Thực hiện tốt - ngắn gọn là linh hồn của wit –

+1

@AdamRackis: Cảm ơn, nhưng bây giờ tôi đã đi và sửa chữa bổ sung của bạn. :) –

+0

@amnotiam, tôi quá muộn rồi, xin lỗi. – OnTheFly

4

Xem câu trả lời của @am không phải là tôi vì sao nó không hoạt động. Tuy nhiên, nếu bạn muốn biết làm thế nào để thực hiện điều này, chuyển nó sang một mảng đầu tiên:

"string".split('').reverse().join(''); // "gnirts" 
+0

+1 '.split()' sẽ là một bộ chuyển đổi mảng tương thích với trình duyệt hơn '[] .slice()'. –

5

Kỹ thuật sau đây (hoặc tương tự) thường được sử dụng để đảo ngược một chuỗi trong JavaScript:

// Don’t use this! 
var naiveReverse = function(string) { 
    return string.split('').reverse().join(''); 
} 

Trong thực tế, tất cả các câu trả lời được đăng cho đến nay là một biến thể của mẫu này. Tuy nhiên, có một số vấn đề với giải pháp này. Ví dụ:

naiveReverse('foo bar'); 
// → 'rab �� oof' 
// Where did the `` symbol go? Whoops! 

Nếu bạn đang tự hỏi tại sao điều này xảy ra, read up on JavaScript’s internal character encoding. (TL; DR:. là một biểu tượng xuất hồn, và JavaScript cho thấy nó như là hai đơn vị mã riêng biệt)

Nhưng có nhiều:

// To see which symbols are being used here, check: 
// http://mothereff.in/js-escapes#1ma%C3%B1ana%20man%CC%83ana 
naiveReverse('mañana mañana'); 
// → 'anãnam anañam' 
// Wait, so now the tilde is applied to the `a` instead of the `n`? WAT. 

Một chuỗi tốt để kiểm tra chuỗi đảo ngược hiện thực là the following:

'foo bar mañana mañana' 

Tại sao? Bởi vì nó có chứa một biểu tượng astral () (là represented by surrogate pairs in JavaScript) và một dấu kết hợp ( trong mañana cuối cùng thực sự bao gồm hai biểu tượng: U + 006E LATIN NHỎ LETTER N và U + 0303 COMBINING TILDE).

Thứ tự mà các cặp thay thế xuất hiện không thể đảo ngược, biểu tượng astral khác sẽ không hiển thị nữa trong chuỗi 'được đảo ngược'. Đó là lý do tại sao bạn thấy những nhãn hiệu �� này ở đầu ra cho ví dụ trước.

Kết hợp nhãn hiệu luôn được áp dụng cho biểu tượng trước, vì vậy bạn phải xem cả biểu tượng chính (U + 006E LATIN SMALL LETTER N) làm dấu kết hợp (U + 0303 COMBINING TILDE). Đảo ngược thứ tự của chúng sẽ khiến cho dấu kết hợp được ghép nối với một biểu tượng khác trong chuỗi. Đó là lý do tại sao đầu ra mẫu có thay vì ñ.

Hy vọng điều này giải thích tại sao tất cả các câu trả lời được đăng cho đến nay là sai.


Để trả lời câu hỏi ban đầu của bạn - làm thế nào để [đúng] đảo ngược một chuỗi trong Javascript -, tôi đã viết một thư viện JavaScript nhỏ mà có khả năng đảo ngược chuỗi Unicode-aware. Nó không có bất kỳ vấn đề nào tôi vừa đề cập. Thư viện được gọi là Esrever; mã của nó là trên GitHub, và nó hoạt động trong khá nhiều môi trường JavaScript. Nó đi kèm với một tiện ích shell/nhị phân, vì vậy bạn có thể dễ dàng đảo ngược chuỗi từ thiết bị đầu cuối của bạn nếu bạn muốn.

var input = 'foo bar mañana mañana'; 
esrever.reverse(input); 
// → 'anañam anañam rab oof' 
Các vấn đề liên quan