Làm thế nào nối chuỗi string trong JS

Chào các bạn, hôm nay mình sẽ giới thiệu đến các bạn 5 cách để nối chuỗi string trong Javascript. Let’s go.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const myCity = 'Đà Nẵng 🏙️';

// 1. dùng toán tử cộng
'stay strong ' + myCity;

// 2. dùng template string (chỉ có ở ES6 trở lên)
`stay strong ${myCity}`;

// 3. dùng concat()
'stay strong '.concat(myCity);

// 4. dùng join()
['stay strong', myCity].join(' ');

// 5.1 tự viết hàm format string
function stringFormat(strTemplate) {
const strArgs = Array.prototype.slice.call(arguments, 1);

return strTemplate.replace(/{(\d+)}/g, function (match, position) {
if (typeof strArgs[position] !== 'undefined') {
return strArgs[position];
}

return match;
});
}
stringFormat('stay strong {0}', myCity);

// 5.2 tự viết hàm format string nhưng dùng prototype
String.prototype.stringFormat = function () {
const strTemplate = this;
const strArgs = arguments;

return strTemplate.replace(/{(\d+)}/g, function (match, position) {
if (typeof strArgs[position] !== 'undefined') {
return strArgs[position];
}

return match;
});
};
'stay strong {0}'.stringFormat(myCity);

// Kết quả
// stay strong Đà Nẵng 🏙️

Template string và Toán tử cộng

Trước đây mình đã có bài viết về các tính năng nổi bật của ES6, template strings là một trong số đó. Ngày xưa khi chưa có template strings, cách phổ biến mình thấy họ hay dùng đó là cộng chuỗi bằng toán tử cộng. Ví dụ.

1
2
3
4
5
6
const myCity = 'Đà Nẵng';
const myCountry = 'Việt Nam';

'Cố lên ' + myCity + ' ơi, cố lên đất nước ' + myCountry + ' tôi ơi, stay strong!';

// Cố lên Đà Nẵng ơi, cố lên đất nước Việt Nam tôi ơi, stay strong!

Ngoài ta toán tử cộng còn một cách kinh điển nữa như sau:

1
2
3
4
5
6
let myCountry = 'Việt Nam';
let myAddress = 'Đà Nẵng';

myAddress += ', ' + myCountry;

console.log(myAddress); // Đà Nẵng, Việt Nam

Bạn thấy có vấn đề gì không, vâng, mình thì mình thấy có 2 vấn đề đó là dễ nhầm, dễ thiếu dấu cộng và khoảng trắng giữa các string. Bây giờ thử dùng template string xem nhé.

1
2
3
4
5
6
const myCity = 'Đà Nẵng';
const myCountry = 'Việt Nam';

`Cố lên ${myCity} ơi, cố lên đất nước ${myCountry} tôi ơi, stay strong!`;

// Cố lên Đà Nẵng ơi, cố lên đất nước Việt Nam tôi ơi, stay strong!

Ngắn hơn dễ nhìn hơn, không bị miss dấu cộng, không nhầm white space -> Code vui hơn.

concat() (function của String)

Khá giống với cách nối chuỗi bằng toán tử cộng, nhưng thay vì dùng dấu cộng, mình sẽ dùng hàm concat(). Các string chỉ cần truyền vào hàm như một tham số, hàm này sẽ nối tất cả string lại và trả về kết quả (trả về string mới).

Vi dụ:

1
2
3
4
5
6
const myCity = 'Đà Nẵng';
const myCountry = 'Việt Nam';

''.concat('Cố lên ', myCity, ' ơi, cố lên đất nước ', myCountry, ' tôi ơi, stay strong!');

// Cố lên Đà Nẵng ơi, cố lên đất nước Việt Nam tôi ơi, stay strong!

Ngoài ra bạn có thể truyền một array vào concat(), khi nhận vào một array, nó sẽ tự động nối tất cả phần tử của array này thành string và ngăn cách nhau bởi dấu phẩy ,. Ví dụ:

1
2
3
4
5
const myAddress = ['Đà Nẵng', 'Việt Nam'];

''.concat(myAddress);

// Đà Nẵng,Việt Nam

Nhìn chung khá oke, khắc phục được chỗ dễ nhầm dấu cộng khi dùng toán tử cộng mà thôi, còn vấn đề với white space vẫn còn đó. Điểm yếu của nó là tốc độ thực thi thua xa toán tử cộng.

Vậy còn cách chi khác không?

join() (function của Array)

Có chứ, đó chính là join(). Vì đây là một function của array nên các bạn cần thêm các chuỗi vào array trước khi nối chuỗi lại. Đại ý các bạn hiểu vậy, nó nhận vào array và trả về string. Ví dụ:

1
2
3
4
5
6
const myCity = 'Đà Nẵng';
const myCountry = 'Việt Nam';

['Cố lên', myCity, 'ơi, cố lên đất nước', myCountry, 'tôi ơi, stay strong!'].join(' ');

// Cố lên Đà Nẵng ơi, cố lên đất nước Việt Nam tôi ơi, stay strong!

Đã khắc chế được vấn đề đã nêu phía trên, code khá gọn.

Các thế mạnh của join:

  • Có thể tùy chỉnh được cách chúng nối lại với nhau (tham số đầu tiên của join). Ví dụ:
1
2
3
4
5
const myAddress = ['Đà Nẵng', 'Việt Nam'];

console.log(myAddress.join(', ')); // Đà Nẵng, Việt Nam
console.log(myAddress.join(',')); // Đà Nẵng,Việt Nam
console.log(myAddress.join(' ')); // Đà Nẵng Việt Nam
  • Không cần dùng tới toán tử cộng và sợ miss white space.
  • Bạn cần nối các chuỗi chưa xác định được số lượng trước. Ví dụ bạn query xuống database lấy lên danh sách thành phố, và in ra tất cả ra thành một chuỗi, cách nhau bởi dấu , .

Tự viết hàm format

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 5.1 tự viết hàm format string
function stringFormat(strTemplate) {
const strArgs = Array.prototype.slice.call(arguments, 1);

return strTemplate.replace(/{(\d+)}/g, function (match, position) {
if (typeof strArgs[position] !== 'undefined') {
return strArgs[position];
}

return match;
});
}
stringFormat('stay strong {0}', myCity);

// 5.2 tự viết hàm format string nhưng dùng prototype
String.prototype.stringFormat = function () {
const strTemplate = this;
const strArgs = arguments;

return strTemplate.replace(/{(\d+)}/g, function (match, position) {
if (typeof strArgs[position] !== 'undefined') {
return strArgs[position];
}

return match;
});
};
'stay strong {0}'.stringFormat(myCity);

Mục đích của chúng như sau, tìm vị trí có cấu trúc {number} thay chúng bằng giá trị khác theo thứ tự truyền vào hàm.

Ở đây mình chỉ giải thích vài chỗ như sau:

  1. Array.prototype.slice.call(arguments, 1);

arguments, các bạn hiểu như vầy, nó là tập hợp tất các tham số các bạn truyền vào một hàm. Ví dụ

1
2
3
4
5
6
// hàm không có khai báo nhận tham số nào, cơ mà arguments lo tất
function add() {
console.log(arguments); // Arguments [1, 2, 3, 4, 5]
}

add(1, 2, 3, 4, 5);

Vì mục đích của hàm này là tìm trong chuỗi mẫu đưa vào, có cấu trúc {number} không, có thì thay thế bằng các tham số khác truyền vào có thứ tự tương ứng. Vì mình gọi stringFormat('stay strong {0}', myCity);, nên tham số đầu tiên arguments[0]'stay strong {0}'. Đây là chuỗi mẫu, nên mình cần loại nó ra trước khi thay thế. Nên call(arguments, 1) số 1 nghĩa là vậy, bỏ 0 lấy từ 1 tới cuối.

arguments không phải là array nên không thể dùng hàm slice (để lấy từ 1 tới cuối) được, nên cần “chuyển về” array và cắt, Array.prototype.slice.call nghĩa là như thế.

Chỗ này bạn đọc call thêm để hiểu: MDN - call()

Đại khái nó gọi slice và truyền vào 1 -> kiểu kiểu như vầy arguments.slice(1); (lưu ý, arguments không thể gọi như vầy nhé, giả dụ để bạn thấy nó hoặc động kiểu vậy).

  1. Regex /{(\d+)}/g

Tìm cấu trúc {number} trong chuỗi mẫu, ví dụ {0}, {1}. Đây gọi là biểu thức chính quy (regex expression).

  1. this

Trong phạm vi bài viết mình đang nói tới this của prototype, các bạn đọc hiểu prototype trước đã hen.

Về cách dùng có hơi khác tý, tùy các bạn chọn. Cách thứ 2 gọi là tùy chỉnh (thêm hàm) Prototype. Giống extension method bên C# vậy đó. Có vài dự án không cho đả đụng tới prototype, và mình cũng nghĩ như vậy, dự án to lên là xác định, tìm chỗ thêm prototype này mệt nghỉ.

Tóm lại

Nên dùng cái nào? Thực ra nó còn tùy vào dự án và style của bạn nữa. Như mình thì thứ tự ưu tiên mình hay dùng là template string và join. Toán tử cộng rất ít khi dùng, lâu lâu. Concat thì never. Hàm tự build thì có, mà trong dự án cũ mà thôi.

Template string không hỗ trợ IE thôi, còn lại tất cả đều được, mấy cái khác thì full, bao gồm IE 5 thì phải. Nói chung quan tâm tới cái này thì lên MDN là thấy ngay.

Tham khảo

 Comments
Comment plugin failed to load
Loading comment plugin