From 2c4c48388cdf5496cc8961520acc640e4a2159b1 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sat, 4 Mar 2023 21:40:38 +0700
Subject: [PATCH 01/13] Update article.md
---
1-js/05-data-types/03-string/article.md | 222 ++++++++++++------------
1 file changed, 111 insertions(+), 111 deletions(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index d5bda9690..9119705ca 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -1,23 +1,23 @@
-# Strings
+# Chuỗi
-In JavaScript, the textual data is stored as strings. There is no separate type for a single character.
+Trong JavaScript, dữ liệu văn bản được lưu trữ dưới dạng chuỗi. Không có loại riêng cho một ký tự.
-The internal format for strings is always [UTF-16](https://en.wikipedia.org/wiki/UTF-16), it is not tied to the page encoding.
+Định dạng bên trong của chuỗi luôn là [UTF-16](https://en.wikipedia.org/wiki/UTF-16), định dạng này không bị ràng buộc với mã hóa trang.
-## Quotes
+## Dấu ngoặc kép
-Let's recall the kinds of quotes.
+Hãy nhớ lại các loại dấu ngoặc kép.
-Strings can be enclosed within either single quotes, double quotes or backticks:
+Các chuỗi có thể được đặt trong dấu ngoặc đơn, dấu ngoặc kép hoặc dấu backticks:
```js
-let single = 'single-quoted';
-let double = "double-quoted";
+let single = 'dấu ngoặc đơn';
+let double = "dấu ngoặc kép";
-let backticks = `backticks`;
+let backticks = `dấu backticks`;
```
-Single and double quotes are essentially the same. Backticks, however, allow us to embed any expression into the string, by wrapping it in `${…}`:
+Dấu ngoặc đơn và dấu ngoặc kép về cơ bản là giống nhau. Tuy nhiên, Backticks cho phép chúng ta nhúng bất kỳ biểu thức nào vào chuỗi, bằng cách gói nó trong `${…}`:
```js run
function sum(a, b) {
@@ -27,7 +27,7 @@ function sum(a, b) {
alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
```
-Another advantage of using backticks is that they allow a string to span multiple lines:
+Một ưu điểm khác của việc sử dụng backticks là chúng cho phép một chuỗi trải dài trên nhiều dòng:
```js run
let guestList = `Guests:
@@ -36,120 +36,120 @@ let guestList = `Guests:
* Mary
`;
-alert(guestList); // a list of guests, multiple lines
+alert(guestList); // một danh sách khách, nhiều dòng
```
-Looks natural, right? But single or double quotes do not work this way.
+Trông tự nhiên nhỉ? Nhưng dấu ngoặc đơn hoặc dấu ngoặc kép không hoạt động theo cách này.
-If we use them and try to use multiple lines, there'll be an error:
+Nếu chúng ta sử dụng chúng và cố gắng sử dụng nhiều dòng, sẽ có lỗi:
```js run
let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John";
```
-Single and double quotes come from ancient times of language creation when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile.
+Dấu ngoặc đơn và dấu ngoặc kép xuất hiện từ thời cổ đại khi tạo ngôn ngữ khi nhu cầu về chuỗi nhiều dòng không được tính đến. Backticks xuất hiện muộn hơn nhiều và do đó linh hoạt hơn.
-Backticks also allow us to specify a "template function" before the first backtick. The syntax is: func`string`. The function `func` is called automatically, receives the string and embedded expressions and can process them. This is called "tagged templates". This feature makes it easier to implement custom templating, but is rarely used in practice. You can read more about it in the [manual](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).
+Backticks cũng cho phép chúng ta chỉ định một "hàm mẫu" trước backtick đầu tiên. Cú pháp là: func`string`. Hàm `func` được gọi tự động, nhận chuỗi và các biểu thức được nhúng và có thể xử lý chúng. Đây được gọi là "mẫu được gắn thẻ". Tính năng này giúp triển khai tạo khuôn mẫu tùy chỉnh dễ dàng hơn nhưng hiếm khi được sử dụng trong thực tế. Bạn có thể đọc thêm về nó trong [hướng dẫn sử dụng](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).
-## Special characters
+## Ký tự đặc biệt
-It is still possible to create multiline strings with single and double quotes by using a so-called "newline character", written as `\n`, which denotes a line break:
+Vẫn có thể tạo chuỗi nhiều dòng với dấu nháy đơn và kép bằng cách sử dụng cái gọi là "ký tự dòng mới", được viết là `\n`, biểu thị ngắt dòng:
```js run
let guestList = "Guests:\n * John\n * Pete\n * Mary";
-alert(guestList); // a multiline list of guests
+alert(guestList); // một danh sách khách nhiều dòng
```
-For example, these two lines are equal, just written differently:
+Ví dụ, hai dòng này bằng nhau, nhưng viết khác nhau:
```js run
-let str1 = "Hello\nWorld"; // two lines using a "newline symbol"
+let str1 = "Hello\nWorld"; // hai dòng sử dụng một "ký tự dòng mới"
-// two lines using a normal newline and backticks
+// hai dòng sử dụng một dòng mới bình thường và backticks
let str2 = `Hello
World`;
alert(str1 == str2); // true
```
-There are other, less common "special" characters.
+Có những ký tự "đặc biệt" khác, ít phổ biến hơn.
-Here's the full list:
+Đây là danh sách đầy đủ:
-| Character | Description |
-|-----------|-------------|
-|`\n`|New line|
-|`\r`|Carriage return: not used alone. Windows text files use a combination of two characters `\r\n` to represent a line break. |
-|`\'`, `\"`|Quotes|
-|`\\`|Backslash|
+| Nhân vật | Mô tả |
+|--------|-------------|
+|`\n`|Dòng mới|
+|`\r`|Trở về đầu hàng: không được sử dụng một mình. Các tệp văn bản Windows sử dụng kết hợp hai ký tự `\r\n` để biểu thị ngắt dòng. |
+|`\'`, `\"`|Trích dẫn|
+|`\\`|Dấu gạch chéo ngược|
|`\t`|Tab|
-|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- kept for compatibility, not used nowadays. |
-|`\xXX`|Unicode character with the given hexadecimal Unicode `XX`, e.g. `'\x7A'` is the same as `'z'`.|
-|`\uXXXX`|A Unicode symbol with the hex code `XXXX` in UTF-16 encoding, for instance `\u00A9` -- is a Unicode for the copyright symbol `©`. It must be exactly 4 hex digits. |
-|`\u{X…XXXXXX}` (1 to 6 hex characters)|A Unicode symbol with the given UTF-32 encoding. Some rare characters are encoded with two Unicode symbols, taking 4 bytes. This way we can insert long codes. |
+|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- được giữ lại để tương thích, không được sử dụng hiện nay. |
+|`\xXX`|Ký tự Unicode với Unicode thập lục phân đã cho `XX`, ví dụ: `'\x7A'` giống như `'z'`.|
+|`\uXXXX`|Một ký hiệu Unicode có mã hex `XXXX` trong mã hóa UTF-16, ví dụ `\u00A9` -- là một ký hiệu Unicode cho ký hiệu bản quyền `©`. Nó phải có chính xác 4 chữ số hex. |
+|`\u{X…XXXXXX}` (1 đến 6 ký tự hex)|Ký hiệu Unicode với mã hóa UTF-32 nhất định. Một số ký tự hiếm được mã hóa bằng hai ký hiệu Unicode, chiếm 4 byte. Bằng cách này, chúng ta có thể chèn mã dài. |
-Examples with Unicode:
+Ví dụ với Unicode:
```js run
alert( "\u00A9" ); // ©
-alert( "\u{20331}" ); // 佫, a rare Chinese hieroglyph (long Unicode)
-alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long Unicode)
+alert( "\u{20331}" ); // 佫, một chữ tượng hình hiếm của Trung Quốc (mã Unicode dài)
+alert( "\u{1F60D}" ); // 😍, một biểu tượng khuôn mặt tươi cười (một mã Unicode dài khác)
```
-All special characters start with a backslash character `\`. It is also called an "escape character".
+Tất cả các ký tự đặc biệt đều bắt đầu bằng ký tự gạch chéo ngược `\`. Nó còn được gọi là "ký tự thoát".
-We might also use it if we wanted to insert a quote into the string.
+Chúng ta cũng có thể sử dụng nó nếu chúng ta muốn chèn một trích dẫn vào chuỗi.
-For instance:
+Ví dụ:
```js run
-alert( 'I*!*\'*/!*m the Walrus!' ); // *!*I'm*/!* the Walrus!
+alert( 'Tôi*!*\*/!*là con hải mã!' ); // *!*Tôi*/!*là con hải mã!
```
-As you can see, we have to prepend the inner quote by the backslash `\'`, because otherwise it would indicate the string end.
+Như bạn có thể thấy, chúng ta phải thêm vào trước trích dẫn bên trong bằng dấu gạch chéo ngược `\'`, vì nếu không nó sẽ cho biết kết thúc chuỗi.
-Of course, only the quotes that are the same as the enclosing ones need to be escaped. So, as a more elegant solution, we could switch to double quotes or backticks instead:
+Tất nhiên, chỉ những trích dẫn giống với những trích dẫn kèm theo mới cần được thoát. Vì vậy, như một giải pháp tao nhã hơn, thay vào đó, chúng ta có thể chuyển sang dấu ngoặc kép hoặc dấu nháy ngược:
```js run
-alert( `I'm the Walrus!` ); // I'm the Walrus!
+alert( `Tôi là con hải mã!` ); // Tôi là con hải mã!
```
-Note that the backslash `\` serves for the correct reading of the string by JavaScript, then disappears. The in-memory string has no `\`. You can clearly see that in `alert` from the examples above.
+Lưu ý rằng dấu gạch chéo ngược `\` phục vụ cho việc đọc chính xác chuỗi bằng JavaScript, sau đó biến mất. Chuỗi trong bộ nhớ không có `\`. Bạn có thể thấy rõ điều đó trong `alert` từ các ví dụ ở trên.
-But what if we need to show an actual backslash `\` within the string?
+Nhưng nếu chúng ta cần hiển thị dấu gạch chéo ngược `\` trong chuỗi thì sao?
-That's possible, but we need to double it like `\\`:
+Điều đó là có thể, nhưng chúng ta cần nhân đôi nó như `\\`:
```js run
-alert( `The backslash: \\` ); // The backslash: \
+alert( `The backslash: \\` ); // Dấu gạch chéo ngược: \
```
-## String length
+## Chiều dài chuỗi
-The `length` property has the string length:
+Thuộc tính `length` có độ dài chuỗi:
```js run
alert( `My\n`.length ); // 3
```
-Note that `\n` is a single "special" character, so the length is indeed `3`.
+Lưu ý rằng `\n` là một ký tự "đặc biệt", vì vậy độ dài thực sự là `3`.
-```warn header="`length` is a property"
-People with a background in some other languages sometimes mistype by calling `str.length()` instead of just `str.length`. That doesn't work.
+```warn header="`length` là thuộc tính"
+Những người có kiến thức cơ bản về một số ngôn ngữ khác đôi khi gõ nhầm bằng cách gọi `str.length()` thay vì chỉ `str.length`. Điều đó không hiệu quả.
-Please note that `str.length` is a numeric property, not a function. There is no need to add parenthesis after it.
+Hãy lưu ý rằng `str.length` là thuộc tính số, không phải hàm. Không cần thêm dấu ngoặc đơn sau nó.
```
-## Accessing characters
+## Truy cập ký tự
-To get a character at position `pos`, use square brackets `[pos]` or call the method [str.charAt(pos)](mdn:js/String/charAt). The first character starts from the zero position:
+Để lấy một ký tự ở vị trí `pos`, hãy sử dụng dấu ngoặc vuông `[pos]` hoặc gọi phương thức [str.charAt(pos)](mdn:js/String/charAt). Ký tự đầu tiên bắt đầu từ vị trí số 0:
```js run
let str = `Hello`;
-// the first character
+// ký tự đầu tiên
alert( str[0] ); // H
alert( str.charAt(0) ); // H
@@ -157,104 +157,104 @@ alert( str.charAt(0) ); // H
alert( str[str.length - 1] ); // o
```
-The square brackets are a modern way of getting a character, while `charAt` exists mostly for historical reasons.
+Dấu ngoặc vuông là một cách hiện đại để lấy một ký tự, trong khi `charAt` chủ yếu tồn tại vì lý do lịch sử.
-The only difference between them is that if no character is found, `[]` returns `undefined`, and `charAt` returns an empty string:
+Sự khác biệt duy nhất giữa chúng là nếu không tìm thấy ký tự nào, `[]` trả về `undefined`, và `charAt` trả về một chuỗi rỗng:
```js run
-let str = `Hello`;
+let str = `Xin chào`;
alert( str[1000] ); // undefined
-alert( str.charAt(1000) ); // '' (an empty string)
+alert( str.charAt(1000) ); // '' (một chuỗi rỗng)
```
-We can also iterate over characters using `for..of`:
+Chúng ta cũng có thể lặp lại các ký tự bằng cách sử dụng `for..of`:
```js run
-for (let char of "Hello") {
- alert(char); // H,e,l,l,o (char becomes "H", then "e", then "l" etc)
+for (let char of "Xin chào") {
+ alert(char); // X,i,n, ,c,h,à,o (char trở thành "X", rồi "i", rồi "n", v.v.)
}
```
-## Strings are immutable
+## Chuỗi là bất biến
-Strings can't be changed in JavaScript. It is impossible to change a character.
+Không thể thay đổi chuỗi trong JavaScript. Không thể thay đổi một nhân vật.
-Let's try it to show that it doesn't work:
+Hãy thử để chứng minh rằng nó không hoạt động:
```js run
-let str = 'Hi';
+let str = 'Chào';
-str[0] = 'h'; // error
-alert( str[0] ); // doesn't work
+str[0] = 'h'; // lỗi
+alert( str[0] ); // không hoạt động
```
-The usual workaround is to create a whole new string and assign it to `str` instead of the old one.
+Cách giải quyết thông thường là tạo một chuỗi hoàn toàn mới và gán nó cho `str` thay vì chuỗi cũ.
-For instance:
+Ví dụ:
```js run
-let str = 'Hi';
+let str = 'Chào';
-str = 'h' + str[1]; // replace the string
+str = 'h' + str[1]; // thay thế chuỗi
-alert( str ); // hi
+alert( str ); // chào
```
-In the following sections we'll see more examples of this.
+Trong các phần sau chúng ta sẽ thấy nhiều ví dụ hơn về điều này.
-## Changing the case
+## Thay đổi kiểu chữ
-Methods [toLowerCase()](mdn:js/String/toLowerCase) and [toUpperCase()](mdn:js/String/toUpperCase) change the case:
+Các phương thức [toLowerCase()](mdn:js/String/toLowerCase) và [toUpperCase()](mdn:js/String/toUpperCase) thay đổi kiểu chữ:
```js run
-alert( 'Interface'.toUpperCase() ); // INTERFACE
-alert( 'Interface'.toLowerCase() ); // interface
+alert( 'Giao diện'.toUpperCase() ); // GIAO DIỆN
+alert( 'Giao diện'.toLowerCase() ); // giao diện
```
-Or, if we want a single character lowercased:
+Hoặc, nếu chúng ta muốn một ký tự được viết thường:
```js
alert( 'Interface'[0].toLowerCase() ); // 'i'
```
-## Searching for a substring
+## Tìm kiếm một chuỗi con
-There are multiple ways to look for a substring within a string.
+Có nhiều cách để tìm kiếm một chuỗi con trong một chuỗi.
### str.indexOf
-The first method is [str.indexOf(substr, pos)](mdn:js/String/indexOf).
+Phương thức đầu tiên là [str.indexOf(substr, pos)](mdn:js/String/indexOf).
-It looks for the `substr` in `str`, starting from the given position `pos`, and returns the position where the match was found or `-1` if nothing can be found.
+Nó tìm kiếm `substr` trong `str`, bắt đầu từ vị trí đã cho `pos` và trả về vị trí tìm thấy kết quả khớp hoặc `-1` nếu không tìm thấy gì.
-For instance:
+Ví dụ:
```js run
-let str = 'Widget with id';
+let str = 'Tiện ích với id';
-alert( str.indexOf('Widget') ); // 0, because 'Widget' is found at the beginning
-alert( str.indexOf('widget') ); // -1, not found, the search is case-sensitive
+alert( str.indexOf('Tiện ích') ); // 0, bởi vì 'Tiện ích' được tìm thấy ngay từ đầu
+alert( str.indexOf('tiện ích') ); // -1, không tìm thấy, tìm kiếm phân biệt chữ hoa chữ thường
-alert( str.indexOf("id") ); // 1, "id" is found at the position 1 (..idget with id)
+alert( str.indexOf("id") ); // 1, "id" được tìm thấy ở vị trí 1 (Tiện ích với id)
```
-The optional second parameter allows us to start searching from a given position.
+Tham số thứ hai tùy chọn cho phép chúng ta bắt đầu tìm kiếm từ một vị trí nhất định.
-For instance, the first occurrence of `"id"` is at position `1`. To look for the next occurrence, let's start the search from position `2`:
+Chẳng hạn, lần xuất hiện đầu tiên của `"id"` là ở vị trí `1`. Để tìm kiếm lần xuất hiện tiếp theo, hãy bắt đầu tìm kiếm từ vị trí `2`:
```js run
-let str = 'Widget with id';
+let str = 'Tiện ích với id';
alert( str.indexOf('id', 2) ) // 12
```
-If we're interested in all occurrences, we can run `indexOf` in a loop. Every new call is made with the position after the previous match:
+Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau vị trí trước đó:
```js run
-let str = 'As sly as a fox, as strong as an ox';
+let str = 'Tinh ranh như một con cáo, mạnh mẽ như một con bò';
-let target = 'as'; // let's look for it
+let target = 'như'; // hãy tìm kiếm nó
let pos = 0;
while (true) {
@@ -262,15 +262,15 @@ while (true) {
if (foundPos == -1) break;
alert( `Found at ${foundPos}` );
- pos = foundPos + 1; // continue the search from the next position
+ pos = foundPos + 1; // tiếp tục tìm kiếm từ vị trí tiếp theo
}
```
-The same algorithm can be layed out shorter:
+Thuật toán tương tự có thể được trình bày ngắn hơn:
```js run
-let str = "As sly as a fox, as strong as an ox";
-let target = "as";
+let str = "Tinh ranh như một con cáo, mạnh mẽ như một con bò";
+let target = "như";
*!*
let pos = -1;
@@ -281,32 +281,32 @@ while ((pos = str.indexOf(target, pos + 1)) != -1) {
```
```smart header="`str.lastIndexOf(substr, position)`"
-There is also a similar method [str.lastIndexOf(substr, position)](mdn:js/String/lastIndexOf) that searches from the end of a string to its beginning.
+Ngoài ra còn có một phương thức tương tự [str.lastIndexOf(substr, position)](mdn:js/String/lastIndexOf) tìm kiếm từ cuối chuỗi đến đầu chuỗi.
-It would list the occurrences in the reverse order.
+Nó sẽ liệt kê các lần xuất hiện theo thứ tự ngược lại.
```
-There is a slight inconvenience with `indexOf` in the `if` test. We can't put it in the `if` like this:
+Có một chút bất tiện với `indexOf` trong bài kiểm tra `if`. Chúng ta không thể đặt nó trong `if` như thế này:
```js run
-let str = "Widget with id";
+let str = "Tiện ích với id";
-if (str.indexOf("Widget")) {
- alert("We found it"); // doesn't work!
+if (str.indexOf("Tiện ích")) {
+ alert("Chúng ta đã tìm thấy nó"); // không hoạt động!
}
```
-The `alert` in the example above doesn't show because `str.indexOf("Widget")` returns `0` (meaning that it found the match at the starting position). Right, but `if` considers `0` to be `false`.
+`alert` trong ví dụ trên không hiển thị vì `str.indexOf("Widget")` trả về `0` (có nghĩa là nó tìm thấy kết quả khớp ở vị trí bắt đầu). Đúng, nhưng `if` coi `0` là `false`.
-So, we should actually check for `-1`, like this:
+Vì vậy, chúng ta thực sự nên kiểm tra `-1`, như sau:
```js run
-let str = "Widget with id";
+let str = "Tiện ích với id";
*!*
-if (str.indexOf("Widget") != -1) {
+if (str.indexOf("Tiện ích") != -1) {
*/!*
- alert("We found it"); // works now!
+ alert("Chúng ta đã tìm thấy nó"); // bây giờ hoạt động!
}
```
From bfa7257664a8b6d19b907af9660c3ababccb434d Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sat, 4 Mar 2023 21:43:35 +0700
Subject: [PATCH 02/13] Update article.md
---
1-js/05-data-types/03-string/article.md | 30 ++++++++++++-------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index 9119705ca..c8a003bc2 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -249,7 +249,7 @@ let str = 'Tiện ích với id';
alert( str.indexOf('id', 2) ) // 12
```
-Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau vị trí trước đó:
+Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau sự trùng hợp trước đó:
```js run
let str = 'Tinh ranh như một con cáo, mạnh mẽ như một con bò';
@@ -310,34 +310,34 @@ if (str.indexOf("Tiện ích") != -1) {
}
```
-#### The bitwise NOT trick
+#### Thủ thuật KHÔNG theo bit
-One of the old tricks used here is the [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) `~` operator. It converts the number to a 32-bit integer (removes the decimal part if exists) and then reverses all bits in its binary representation.
+Một trong những thủ thuật cũ được sử dụng ở đây là toán tử [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) `~`. Nó chuyển đổi số thành số nguyên 32 bit (loại bỏ phần thập phân nếu có) và sau đó đảo ngược tất cả các bit trong biểu diễn nhị phân của nó.
-In practice, that means a simple thing: for 32-bit integers `~n` equals `-(n+1)`.
+Trong thực tế, điều đó có nghĩa là một điều đơn giản: đối với số nguyên 32 bit `~n` bằng `-(n+1)`.
-For instance:
+Ví dụ:
```js run
-alert( ~2 ); // -3, the same as -(2+1)
-alert( ~1 ); // -2, the same as -(1+1)
-alert( ~0 ); // -1, the same as -(0+1)
+alert( ~2 ); // -3, giống như -(2+1)
+alert( ~1 ); // -2, giống như -(1+1)
+alert( ~0 ); // -1, giống như -(0+1)
*!*
-alert( ~-1 ); // 0, the same as -(-1+1)
+alert( ~-1 ); // 0, giống như -(-1+1)
*/!*
```
-As we can see, `~n` is zero only if `n == -1` (that's for any 32-bit signed integer `n`).
+Như chúng ta có thể thấy, `~n` chỉ bằng 0 nếu `n == -1` (đó là đối với bất kỳ số nguyên có dấu 32 bit nào `n`).
-So, the test `if ( ~str.indexOf("...") )` is truthy only if the result of `indexOf` is not `-1`. In other words, when there is a match.
+Vì vậy, phép thử `if ( ~str.indexOf("...") )` chỉ đúng nếu kết quả của `indexOf` không phải là `-1`. Nói cách khác, khi có một sự trùng hợp.
-People use it to shorten `indexOf` checks:
+Mọi người sử dụng nó để rút ngắn kiểm tra `indexOf`:
```js run
-let str = "Widget";
+let str = "Tiện ích";
-if (~str.indexOf("Widget")) {
- alert( 'Found it!' ); // works
+if (~str.indexOf("Tiện ích")) {
+ alert( 'Đã tìm thấy nó·!' ); // hoạt động
}
```
From 9093f729f58c3c44d3bba0270e82d36261b85948 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 13:40:55 +0700
Subject: [PATCH 03/13] Update article.md
---
1-js/05-data-types/03-string/article.md | 34 ++++++++++++-------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index c8a003bc2..0bfe51674 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -249,7 +249,7 @@ let str = 'Tiện ích với id';
alert( str.indexOf('id', 2) ) // 12
```
-Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau sự trùng hợp trước đó:
+Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau sự trùng khớp trước đó:
```js run
let str = 'Tinh ranh như một con cáo, mạnh mẽ như một con bò';
@@ -329,7 +329,7 @@ alert( ~-1 ); // 0, giống như -(-1+1)
Như chúng ta có thể thấy, `~n` chỉ bằng 0 nếu `n == -1` (đó là đối với bất kỳ số nguyên có dấu 32 bit nào `n`).
-Vì vậy, phép thử `if ( ~str.indexOf("...") )` chỉ đúng nếu kết quả của `indexOf` không phải là `-1`. Nói cách khác, khi có một sự trùng hợp.
+Vì vậy, phép thử `if ( ~str.indexOf("...") )` chỉ đúng nếu kết quả của `indexOf` không phải là `-1`. Nói cách khác, khi có một sự trùng khớp.
Mọi người sử dụng nó để rút ngắn kiểm tra `indexOf`:
@@ -341,19 +341,19 @@ if (~str.indexOf("Tiện ích")) {
}
```
-It is usually not recommended to use language features in a non-obvious way, but this particular trick is widely used in old code, so we should understand it.
+Thông thường không nên sử dụng các tính năng ngôn ngữ theo cách không rõ ràng, nhưng thủ thuật cụ thể này được sử dụng rộng rãi trong mã cũ, vì vậy chúng ta nên hiểu nó.
-Just remember: `if (~str.indexOf(...))` reads as "if found".
+Chỉ cần nhớ: `if (~str.indexOf(...))` đọc là "nếu tìm thấy".
-To be precise though, as big numbers are truncated to 32 bits by `~` operator, there exist other numbers that give `0`, the smallest is `~4294967295=0`. That makes such check correct only if a string is not that long.
+Tuy nhiên, nói một cách chính xác, vì các số lớn bị cắt bớt thành 32 bit bởi toán tử `~`, nên tồn tại các số khác cho `0`, số nhỏ nhất là `~4294967295=0`. Điều đó làm cho kiểm tra như vậy chỉ chính xác nếu một chuỗi không dài.
-Right now we can see this trick only in the old code, as modern JavaScript provides `.includes` method (see below).
+Hiện tại, chúng ta chỉ có thể thấy thủ thuật này trong mã cũ, vì JavaScript hiện đại cung cấp phương thức `.includes` (xem bên dưới).
### includes, startsWith, endsWith
-The more modern method [str.includes(substr, pos)](mdn:js/String/includes) returns `true/false` depending on whether `str` contains `substr` within.
+Phương thức hiện đại hơn [str.includes(substr, pos)](mdn:js/String/includes) trả về `true/false` tùy thuộc vào việc `str` có chứa `substr` bên trong hay không.
-It's the right choice if we need to test for the match, but don't need its position:
+Đó là lựa chọn phù hợp nếu chúng ta cần kiểm tra sự trùng khớp, nhưng không cần vị trí của nó:
```js run
alert( "Widget with id".includes("Widget") ); // true
@@ -361,28 +361,28 @@ alert( "Widget with id".includes("Widget") ); // true
alert( "Hello".includes("Bye") ); // false
```
-The optional second argument of `str.includes` is the position to start searching from:
+Đối số thứ hai tùy chọn của `str.includes` là vị trí để bắt đầu tìm kiếm từ:
```js run
alert( "Widget".includes("id") ); // true
-alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id"
+alert( "Widget".includes("id", 3) ); // false, từ vị trí 3 không có "id"
```
-The methods [str.startsWith](mdn:js/String/startsWith) and [str.endsWith](mdn:js/String/endsWith) do exactly what they say:
+Các phương thức [str.startsWith](mdn:js/String/startsWith) và [str.endsWith](mdn:js/String/endsWith) thực hiện chính xác những gì chúng nói:
```js run
-alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid"
-alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get"
+alert( "Widget".startsWith("Wid") ); // true, "Tiện ích" bắt đầu bằng "Tiện"
+alert( "Widget".endsWith("get") ); // true, "Tiện ích" kết thúc bằng "ích"
```
-## Getting a substring
+## Lấy một chuỗi con
-There are 3 methods in JavaScript to get a substring: `substring`, `substr` and `slice`.
+Có 3 phương thức trong JavaScript để lấy chuỗi con: `substring`, `substr` và `slice`.
`str.slice(start [, end])`
-: Returns the part of the string from `start` to (but not including) `end`.
+: Trả về một phần của chuỗi từ `start` đến (nhưng không bao gồm) `end`.
- For instance:
+ Ví dụ:
```js run
let str = "stringify";
From d040e8bae48e3bc8f64ad1735e41b574527e1fb6 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:14:22 +0700
Subject: [PATCH 04/13] Update article.md
---
1-js/05-data-types/03-string/article.md | 288 ++++++++++++------------
1 file changed, 143 insertions(+), 145 deletions(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index 0bfe51674..7a6517250 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -105,7 +105,7 @@ Chúng ta cũng có thể sử dụng nó nếu chúng ta muốn chèn một tr
Ví dụ:
```js run
-alert( 'Tôi*!*\*/!*là con hải mã!' ); // *!*Tôi*/!*là con hải mã!
+alert( 'I*!*\'*/!*m the Walrus!' ); // *!*I'm*/!* the Walrus!
```
Như bạn có thể thấy, chúng ta phải thêm vào trước trích dẫn bên trong bằng dấu gạch chéo ngược `\'`, vì nếu không nó sẽ cho biết kết thúc chuỗi.
@@ -113,7 +113,7 @@ Như bạn có thể thấy, chúng ta phải thêm vào trước trích dẫn b
Tất nhiên, chỉ những trích dẫn giống với những trích dẫn kèm theo mới cần được thoát. Vì vậy, như một giải pháp tao nhã hơn, thay vào đó, chúng ta có thể chuyển sang dấu ngoặc kép hoặc dấu nháy ngược:
```js run
-alert( `Tôi là con hải mã!` ); // Tôi là con hải mã!
+alert( `I'm the Walrus!` ); // I'm the Walrus!
```
Lưu ý rằng dấu gạch chéo ngược `\` phục vụ cho việc đọc chính xác chuỗi bằng JavaScript, sau đó biến mất. Chuỗi trong bộ nhớ không có `\`. Bạn có thể thấy rõ điều đó trong `alert` từ các ví dụ ở trên.
@@ -171,8 +171,8 @@ alert( str.charAt(1000) ); // '' (một chuỗi rỗng)
Chúng ta cũng có thể lặp lại các ký tự bằng cách sử dụng `for..of`:
```js run
-for (let char of "Xin chào") {
- alert(char); // X,i,n, ,c,h,à,o (char trở thành "X", rồi "i", rồi "n", v.v.)
+for (let char of "Hello") {
+ alert(char); // H,e,l,l,o (char trở thành "H", rồi "e", rồi "l", v.v.)
}
```
@@ -183,7 +183,7 @@ Không thể thay đổi chuỗi trong JavaScript. Không thể thay đổi mộ
Hãy thử để chứng minh rằng nó không hoạt động:
```js run
-let str = 'Chào';
+let str = 'Hi';
str[0] = 'h'; // lỗi
alert( str[0] ); // không hoạt động
@@ -194,11 +194,11 @@ Cách giải quyết thông thường là tạo một chuỗi hoàn toàn mới
Ví dụ:
```js run
-let str = 'Chào';
+let str = 'Hi';
str = 'h' + str[1]; // thay thế chuỗi
-alert( str ); // chào
+alert( str ); // hi
```
Trong các phần sau chúng ta sẽ thấy nhiều ví dụ hơn về điều này.
@@ -208,8 +208,8 @@ Trong các phần sau chúng ta sẽ thấy nhiều ví dụ hơn về điều n
Các phương thức [toLowerCase()](mdn:js/String/toLowerCase) và [toUpperCase()](mdn:js/String/toUpperCase) thay đổi kiểu chữ:
```js run
-alert( 'Giao diện'.toUpperCase() ); // GIAO DIỆN
-alert( 'Giao diện'.toLowerCase() ); // giao diện
+ alert( 'Interface'.toUpperCase() ); // INTERFACE
+alert( 'Interface'.toLowerCase() ); // Interface
```
Hoặc, nếu chúng ta muốn một ký tự được viết thường:
@@ -231,12 +231,12 @@ Nó tìm kiếm `substr` trong `str`, bắt đầu từ vị trí đã cho `pos`
Ví dụ:
```js run
-let str = 'Tiện ích với id';
+let str = 'Widget with id';
-alert( str.indexOf('Tiện ích') ); // 0, bởi vì 'Tiện ích' được tìm thấy ngay từ đầu
-alert( str.indexOf('tiện ích') ); // -1, không tìm thấy, tìm kiếm phân biệt chữ hoa chữ thường
+alert( str.indexOf('Widget') ); // 0, bởi vì 'Widget' được tìm thấy ngay từ đầu
+alert( str.indexOf('widget') ); // -1, không tìm thấy, tìm kiếm phân biệt chữ hoa chữ thường
-alert( str.indexOf("id") ); // 1, "id" được tìm thấy ở vị trí 1 (Tiện ích với id)
+alert( str.indexOf("id") ); // 1, "id" được tìm thấy ở vị trí 1 (..idget với id)
```
Tham số thứ hai tùy chọn cho phép chúng ta bắt đầu tìm kiếm từ một vị trí nhất định.
@@ -244,24 +244,24 @@ Tham số thứ hai tùy chọn cho phép chúng ta bắt đầu tìm kiếm t
Chẳng hạn, lần xuất hiện đầu tiên của `"id"` là ở vị trí `1`. Để tìm kiếm lần xuất hiện tiếp theo, hãy bắt đầu tìm kiếm từ vị trí `2`:
```js run
-let str = 'Tiện ích với id';
+let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12
```
-Nếu chúng tôi quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau sự trùng khớp trước đó:
+Nếu chúng ta quan tâm đến tất cả các lần xuất hiện, chúng tôi có thể chạy `indexOf` trong một vòng lặp. Mỗi cuộc gọi mới được thực hiện với vị trí sau sự trùng khớp trước đó:
```js run
-let str = 'Tinh ranh như một con cáo, mạnh mẽ như một con bò';
+let str = 'As sly as a fox, as strong as an ox';
-let target = 'như'; // hãy tìm kiếm nó
+let target = 'as'; // hãy tìm kiếm nó
let pos = 0;
while (true) {
let foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
- alert( `Found at ${foundPos}` );
+ alert( `Đã tìm thấy tại ${foundPos}` );
pos = foundPos + 1; // tiếp tục tìm kiếm từ vị trí tiếp theo
}
```
@@ -269,8 +269,8 @@ while (true) {
Thuật toán tương tự có thể được trình bày ngắn hơn:
```js run
-let str = "Tinh ranh như một con cáo, mạnh mẽ như một con bò";
-let target = "như";
+let str = "As sly as a fox, as strong as an ox";
+let target = "as";
*!*
let pos = -1;
@@ -289,9 +289,9 @@ Nó sẽ liệt kê các lần xuất hiện theo thứ tự ngược lại.
Có một chút bất tiện với `indexOf` trong bài kiểm tra `if`. Chúng ta không thể đặt nó trong `if` như thế này:
```js run
-let str = "Tiện ích với id";
+let str = "Widget with id";
-if (str.indexOf("Tiện ích")) {
+if (str.indexOf("Widget")) {
alert("Chúng ta đã tìm thấy nó"); // không hoạt động!
}
```
@@ -301,10 +301,10 @@ if (str.indexOf("Tiện ích")) {
Vì vậy, chúng ta thực sự nên kiểm tra `-1`, như sau:
```js run
-let str = "Tiện ích với id";
+let str = "Widget with id";
*!*
-if (str.indexOf("Tiện ích") != -1) {
+if (str.indexOf("Widget") != -1) {
*/!*
alert("Chúng ta đã tìm thấy nó"); // bây giờ hoạt động!
}
@@ -334,9 +334,9 @@ Vì vậy, phép thử `if ( ~str.indexOf("...") )` chỉ đúng nếu kết qu
Mọi người sử dụng nó để rút ngắn kiểm tra `indexOf`:
```js run
-let str = "Tiện ích";
+let str = "Widget";
-if (~str.indexOf("Tiện ích")) {
+if (~str.indexOf("Widget")) {
alert( 'Đã tìm thấy nó·!' ); // hoạt động
}
```
@@ -371,8 +371,8 @@ alert( "Widget".includes("id", 3) ); // false, từ vị trí 3 không có "id"
Các phương thức [str.startsWith](mdn:js/String/startsWith) và [str.endsWith](mdn:js/String/endsWith) thực hiện chính xác những gì chúng nói:
```js run
-alert( "Widget".startsWith("Wid") ); // true, "Tiện ích" bắt đầu bằng "Tiện"
-alert( "Widget".endsWith("get") ); // true, "Tiện ích" kết thúc bằng "ích"
+alert( "Widget".startsWith("Wid") ); // true, "Widget" bắt đầu bằng "Wid"
+alert( "Widget".endsWith("get") ); // true, "Widget" kết thúc bằng "get"
```
## Lấy một chuỗi con
@@ -386,127 +386,127 @@ Có 3 phương thức trong JavaScript để lấy chuỗi con: `substring`, `su
```js run
let str = "stringify";
- alert( str.slice(0, 5) ); // 'strin', the substring from 0 to 5 (not including 5)
- alert( str.slice(0, 1) ); // 's', from 0 to 1, but not including 1, so only character at 0
+ alert( str.slice(0, 5) ); // 'strin', chuỗi con từ 0 đến 5 (không bao gồm 5)
+ alert( str.slice(0, 1) ); // 's', từ 0 đến 1, nhưng không bao gồm 1, vì vậy chỉ ký tự ở 0
```
- If there is no second argument, then `slice` goes till the end of the string:
+ Nếu không có đối số thứ hai, thì `slice` sẽ đi đến cuối chuỗi:
```js run
let str = "st*!*ringify*/!*";
- alert( str.slice(2) ); // 'ringify', from the 2nd position till the end
+ alert( str.slice(2) ); // 'ringify', từ vị trí thứ 2 đến cuối
```
- Negative values for `start/end` are also possible. They mean the position is counted from the string end:
+ Cũng có thể có các giá trị âm cho `start/end`. Chúng có nghĩa là vị trí được tính từ cuối chuỗi:
```js run
let str = "strin*!*gif*/!*y";
- // start at the 4th position from the right, end at the 1st from the right
+ // bắt đầu ở vị trí thứ 4 từ bên phải, kết thúc ở vị trí thứ 1 từ bên phải
alert( str.slice(-4, -1) ); // 'gif'
```
`str.substring(start [, end])`
-: Returns the part of the string *between* `start` and `end`.
+: Trả về một phần của chuỗi *giữa* `start` và `end`.
- This is almost the same as `slice`, but it allows `start` to be greater than `end`.
+ Điều này gần giống với `slice`, nhưng nó cho phép `start` lớn hơn `end`.
- For instance:
+ Ví dụ:
```js run
let str = "st*!*ring*/!*ify";
- // these are same for substring
+ // những cái này giống nhau đối với chuỗi con
alert( str.substring(2, 6) ); // "ring"
alert( str.substring(6, 2) ); // "ring"
- // ...but not for slice:
- alert( str.slice(2, 6) ); // "ring" (the same)
- alert( str.slice(6, 2) ); // "" (an empty string)
+ // ...nhưng không phải cho lát cắt:
+ alert( str.slice(2, 6) ); // "ring" (giống nhau)
+ alert( str.slice(6, 2) ); // "" (một chuỗi rỗng)
```
- Negative arguments are (unlike slice) not supported, they are treated as `0`.
+ Các đối số phủ định (không giống như lát cắt) không được hỗ trợ, chúng được coi là `0`.
`str.substr(start [, length])`
-: Returns the part of the string from `start`, with the given `length`.
+: Trả về một phần của chuỗi từ `bắt đầu`, với `độ dài` đã cho.
- In contrast with the previous methods, this one allows us to specify the `length` instead of the ending position:
+ Ngược lại với các phương pháp trước, phương pháp này cho phép chúng ta chỉ định `độ dài` thay vì vị trí kết thúc:
```js run
let str = "st*!*ring*/!*ify";
- alert( str.substr(2, 4) ); // 'ring', from the 2nd position get 4 characters
+ alert( str.substr(2, 4) ); // 'ring', từ vị trí thứ 2 nhận được 4 ký tự
```
- The first argument may be negative, to count from the end:
+ Đối số đầu tiên có thể là số âm, được tính từ cuối:
```js run
let str = "strin*!*gi*/!*fy";
- alert( str.substr(-4, 2) ); // 'gi', from the 4th position get 2 characters
+ alert( str.substr(-4, 2) ); // 'gi', từ vị trí thứ 4 lấy 2 ký tự
```
-Let's recap these methods to avoid any confusion:
+Hãy tóm tắt lại các phương pháp này để tránh nhầm lẫn:
-| method | selects... | negatives |
-|--------|-----------|-----------|
-| `slice(start, end)` | from `start` to `end` (not including `end`) | allows negatives |
-| `substring(start, end)` | between `start` and `end` | negative values mean `0` |
-| `substr(start, length)` | from `start` get `length` characters | allows negative `start` |
+| phương pháp | chọn... | âm bản |
+|---|------------|--------|
+| `slice(start, end)` | từ `start` đến `end` (không bao gồm `end`) | cho phép số âm |
+| `substring(start, end)` | giữa `start` và `end` | giá trị âm có nghĩa là `0` |
+| `substr(start, length)` | từ `start` lấy các ký tự `length` | cho phép `start` âm |
-```smart header="Which one to choose?"
-All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
+```smart header="Chọn cái nào?"
+Tất cả chúng có thể làm công việc. Về mặt hình thức, `substr` có một nhược điểm nhỏ: nó không được mô tả trong thông số kỹ thuật JavaScript cốt lõi mà trong Phụ lục B, bao gồm các tính năng chỉ dành cho trình duyệt tồn tại chủ yếu vì lý do lịch sử. Vì vậy, các môi trường không có trình duyệt có thể không hỗ trợ nó. Nhưng trong thực tế, nó hoạt động ở mọi nơi.
-Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write. So, it's enough to remember solely `slice` of these three methods.
+Trong số hai biến thể còn lại, `slice` linh hoạt hơn một chút, nó cho phép đối số âm và viết ngắn hơn. Vì vậy, chỉ cần nhớ `slice` của ba phương pháp này là đủ.
```
-## Comparing strings
+## So sánh chuỗi
-As we know from the chapter , strings are compared character-by-character in alphabetical order.
+Như chúng ta đã biết từ chương , các chuỗi được so sánh theo từng ký tự theo thứ tự bảng chữ cái.
-Although, there are some oddities.
+Mặc dù, có một số điều kỳ lạ.
-1. A lowercase letter is always greater than the uppercase:
+1. Chữ thường luôn lớn hơn chữ hoa:
```js run
alert( 'a' > 'Z' ); // true
```
-2. Letters with diacritical marks are "out of order":
+2. Các chữ cái có dấu phụ là "không theo thứ tự":
```js run
alert( 'Österreich' > 'Zealand' ); // true
```
- This may lead to strange results if we sort these country names. Usually people would expect `Zealand` to come after `Österreich` in the list.
+ Điều này có thể dẫn đến kết quả lạ nếu chúng ta sắp xếp các tên quốc gia này. Thông thường mọi người sẽ mong đợi `Zealand` sẽ đứng sau `Österreich` trong danh sách.
-To understand what happens, let's review the internal representation of strings in JavaScript.
+Để hiểu điều gì xảy ra, hãy xem lại biểu diễn bên trong của chuỗi trong JavaScript.
-All strings are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). That is: each character has a corresponding numeric code. There are special methods that allow to get the character for the code and back.
+Tất cả các chuỗi được mã hóa bằng [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Đó là: mỗi ký tự có một mã số tương ứng. Có những phương pháp đặc biệt cho phép lấy ký tự cho mã và ngược lại.
`str.codePointAt(pos)`
-: Returns the code for the character at position `pos`:
+: Trả về mã cho ký tự tại vị trí `pos`:
```js run
- // different case letters have different codes
+ // các chữ cái viết hoa và viết thường có mã khác nhau
alert( "z".codePointAt(0) ); // 122
alert( "Z".codePointAt(0) ); // 90
```
`String.fromCodePoint(code)`
-: Creates a character by its numeric `code`
+: Tạo một ký tự bằng số `code` của nó
```js run
alert( String.fromCodePoint(90) ); // Z
```
- We can also add Unicode characters by their codes using `\u` followed by the hex code:
+ Chúng ta cũng có thể thêm các ký tự Unicode theo mã của chúng bằng cách sử dụng `\u` theo sau là mã hex:
```js run
- // 90 is 5a in hexadecimal system
+ // 90 là 5a trong hệ thập lục phân
alert( '\u005a' ); // Z
```
-Now let's see the characters with codes `65..220` (the latin alphabet and a little bit extra) by making a string of them:
+Bây giờ, hãy xem các ký tự có mã `65..220` (bảng chữ cái Latinh và thêm một chút) bằng cách tạo một chuỗi gồm chúng:
```js run
let str = '';
@@ -515,139 +515,137 @@ for (let i = 65; i <= 220; i++) {
str += String.fromCodePoint(i);
}
alert( str );
-// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
-// ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ
+// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+// ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ
```
-See? Capital characters go first, then a few special ones, then lowercase characters, and `Ö` near the end of the output.
+Thấy chưa? Các ký tự viết hoa xuất hiện trước, sau đó là một vài ký tự đặc biệt, sau đó là các ký tự viết thường và `Ö` ở gần cuối đầu ra.
-Now it becomes obvious why `a > Z`.
+Bây giờ thì rõ ràng là tại sao `a > Z`.
-The characters are compared by their numeric code. The greater code means that the character is greater. The code for `a` (97) is greater than the code for `Z` (90).
+Các ký tự được so sánh bằng mã số của chúng. Mã lớn hơn có nghĩa là ký tự lớn hơn. Mã của `a` (97) lớn hơn mã của `Z` (90).
-- All lowercase letters go after uppercase letters because their codes are greater.
-- Some letters like `Ö` stand apart from the main alphabet. Here, it's code is greater than anything from `a` to `z`.
+- Tất cả các chữ thường đi sau các chữ in hoa vì mã của chúng lớn hơn.
+- Một số chữ cái như `Ö` đứng ngoài bảng chữ cái chính. Ở đây, mã của nó lớn hơn bất kỳ thứ gì từ `a` đến `z`.
-### Correct comparisons [#correct-comparisons]
+### So sánh đúng [#true-comparisons]
-The "right" algorithm to do string comparisons is more complex than it may seem, because alphabets are different for different languages.
+Thuật toán "đúng" để thực hiện so sánh chuỗi phức tạp hơn vẻ ngoài của nó, bởi vì các bảng chữ cái khác nhau đối với các ngôn ngữ khác nhau.
-So, the browser needs to know the language to compare.
+Vì vậy, trình duyệt cần biết ngôn ngữ để so sánh.
-Luckily, all modern browsers (IE10- requires the additional library [Intl.js](https://github.com/andyearnshaw/Intl.js/)) support the internationalization standard [ECMA-402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf).
+May mắn thay, tất cả các trình duyệt hiện đại (IE10- yêu cầu thư viện bổ sung [Intl.js](https://github.com/andyearnshaw/Intl.js/)) đều hỗ trợ tiêu chuẩn quốc tế hóa [ECMA-402](http://www. ecma-international.org/ecma-402/1.0/ECMA-402.pdf).
-It provides a special method to compare strings in different languages, following their rules.
+Nó cung cấp một phương pháp đặc biệt để so sánh các chuỗi trong các ngôn ngữ khác nhau, tuân theo các quy tắc của chúng.
-The call [str.localeCompare(str2)](mdn:js/String/localeCompare) returns an integer indicating whether `str` is less, equal or greater than `str2` according to the language rules:
+Lệnh gọi [str.localeCompare(str2)](mdn:js/String/localeCompare) trả về một số nguyên cho biết `str` nhỏ hơn, bằng hay lớn hơn `str2` theo quy tắc ngôn ngữ:
-- Returns a negative number if `str` is less than `str2`.
-- Returns a positive number if `str` is greater than `str2`.
-- Returns `0` if they are equivalent.
+- Trả về số âm nếu `str` nhỏ hơn `str2`.
+- Trả về một số dương nếu `str` lớn hơn `str2`.
+- Trả về `0` nếu chúng bằng nhau.
-For instance:
+Ví dụ:
```js run
alert( 'Österreich'.localeCompare('Zealand') ); // -1
```
-This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment, letter order depends on the language) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc.
-
-## Internals, Unicode
+Phương thức này thực sự có hai đối số bổ sung được chỉ định trong [tài liệu](mdn:js/String/localeCompare), cho phép phương thức này chỉ định ngôn ngữ (theo mặc định được lấy từ môi trường, thứ tự chữ cái phụ thuộc vào ngôn ngữ) và thiết lập các quy tắc bổ sung như phân biệt chữ hoa chữ thường hoặc nên coi `"a"` và `"á"` như nhau, v.v.
-```warn header="Advanced knowledge"
-The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical or hieroglyphic characters or other rare symbols.
+## Kiến thức nâng cao"
+Phần này đi sâu hơn vào bên trong chuỗi. Kiến thức này sẽ hữu ích cho bạn nếu bạn định xử lý biểu tượng cảm xúc, ký tự toán học hoặc chữ tượng hình hiếm hoặc các ký hiệu hiếm khác.
-You can skip the section if you don't plan to support them.
+Bạn có thể bỏ qua phần này nếu bạn không có kế hoạch hỗ trợ chúng.
```
-### Surrogate pairs
+### Cặp thay thế
-All frequently used characters have 2-byte codes. Letters in most european languages, numbers, and even most hieroglyphs, have a 2-byte representation.
+Tất cả các ký tự được sử dụng thường xuyên đều có mã 2 byte. Các chữ cái trong hầu hết các ngôn ngữ châu Âu, số và thậm chí hầu hết các chữ tượng hình đều có biểu diễn 2 byte.
-But 2 bytes only allow 65536 combinations and that's not enough for every possible symbol. So rare symbols are encoded with a pair of 2-byte characters called "a surrogate pair".
+Nhưng 2 byte chỉ cho phép 65536 kết hợp và điều đó là không đủ cho mọi biểu tượng có thể. Vì vậy, các ký hiệu hiếm được mã hóa bằng một cặp ký tự 2 byte được gọi là "cặp thay thế".
-The length of such symbols is `2`:
+Độ dài của các ký hiệu như vậy là `2`:
```js run
-alert( '𝒳'.length ); // 2, MATHEMATICAL SCRIPT CAPITAL X
-alert( '😂'.length ); // 2, FACE WITH TEARS OF JOY
-alert( '𩷶'.length ); // 2, a rare Chinese hieroglyph
+alert( '𝒳'.length ); // 2, CHỮ VIẾT HOA TOÁN HỌC X
+alert( '😂'.length ); // 2, MẶT VỚI GIỌT NƯỚC MẮT VUI
+alert( '𩷶'.length ); // 2, một chữ tượng hình hiếm của Trung Quốc
```
-Note that surrogate pairs did not exist at the time when JavaScript was created, and thus are not correctly processed by the language!
+Lưu ý rằng các cặp thay thế không tồn tại vào thời điểm JavaScript được tạo và do đó không được ngôn ngữ xử lý chính xác!
-We actually have a single symbol in each of the strings above, but the `length` shows a length of `2`.
+Chúng ta thực sự có một ký hiệu duy nhất trong mỗi chuỗi ở trên, nhưng `độ dài` hiển thị độ dài `2`.
-`String.fromCodePoint` and `str.codePointAt` are few rare methods that deal with surrogate pairs right. They recently appeared in the language. Before them, there were only [String.fromCharCode](mdn:js/String/fromCharCode) and [str.charCodeAt](mdn:js/String/charCodeAt). These methods are actually the same as `fromCodePoint/codePointAt`, but don't work with surrogate pairs.
+`String.fromCodePoint` và `str.codePointAt` là một vài phương pháp hiếm hoi đối phó với các cặp thay thế đúng. Gần đây chúng đã xuất hiện trong ngôn ngữ. Trước chúng, đã chỉ có [String.fromCharCode](mdn:js/String/fromCharCode) và [str.charCodeAt](mdn:js/String/charCodeAt). Những phương pháp này thực sự giống như `fromCodePoint/codePointAt`, nhưng không hoạt động với các cặp thay thế.
-Getting a symbol can be tricky, because surrogate pairs are treated as two characters:
+Lấy một biểu tượng có thể khó khăn, bởi vì các cặp thay thế được coi là hai ký tự:
```js run
-alert( '𝒳'[0] ); // strange symbols...
-alert( '𝒳'[1] ); // ...pieces of the surrogate pair
+alert( '𝒳'[0] ); // ký tự lạ...
+alert( '𝒳'[1] ); // ...các mảnh của cặp thay thế
```
-Note that pieces of the surrogate pair have no meaning without each other. So the alerts in the example above actually display garbage.
+Lưu ý rằng các phần của cặp thay thế không có ý nghĩa gì nếu không có nhau. Vì vậy, các cảnh báo trong ví dụ trên thực sự hiển thị rác.
-Technically, surrogate pairs are also detectable by their codes: if a character has the code in the interval of `0xd800..0xdbff`, then it is the first part of the surrogate pair. The next character (second part) must have the code in interval `0xdc00..0xdfff`. These intervals are reserved exclusively for surrogate pairs by the standard.
+Về mặt kỹ thuật, các cặp thay thế cũng có thể được phát hiện bằng mã của chúng: nếu một ký tự có mã trong khoảng `0xd800..0xdbff`, thì đó là phần đầu tiên của cặp thay thế. Ký tự tiếp theo (phần thứ hai) phải có mã trong khoảng `0xdc00..0xdfff`. Các khoảng thời gian này được dành riêng cho các cặp thay thế theo tiêu chuẩn.
-In the case above:
+Trong trường hợp trên:
```js run
-// charCodeAt is not surrogate-pair aware, so it gives codes for parts
+// charCodeAt không nhận biết cặp thay thế, vì vậy nó cung cấp mã cho các bộ phận
-alert( '𝒳'.charCodeAt(0).toString(16) ); // d835, between 0xd800 and 0xdbff
-alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3, between 0xdc00 and 0xdfff
+alert( '𝒳'.charCodeAt(0).toString(16) ); // d835, giữa 0xd800 và 0xdbff
+alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3, giữa 0xdc00 và 0xdfff
```
-You will find more ways to deal with surrogate pairs later in the chapter . There are probably special libraries for that too, but nothing famous enough to suggest here.
+Bạn sẽ tìm thấy nhiều cách hơn để xử lý các cặp thay thế ở phần sau của chương . Có thể có những thư viện đặc biệt cho điều đó, nhưng không có gì đủ nổi tiếng để đề xuất ở đây.
-### Diacritical marks and normalization
+### Dấu phụ và chuẩn hóa
-In many languages there are symbols that are composed of the base character with a mark above/under it.
+Trong nhiều ngôn ngữ, có những ký hiệu bao gồm ký tự cơ sở có dấu ở trên/dưới ký tự đó.
-For instance, the letter `a` can be the base character for: `àáâäãåā`. Most common "composite" character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations.
+Chẳng hạn, chữ `a` có thể là ký tự cơ sở cho: `àáâäãåā`. Hầu hết các ký tự "tổng hợp" phổ biến đều có mã riêng trong bảng UTF-16. Nhưng không phải tất cả chúng, bởi vì có quá nhiều kết hợp có thể.
-To support arbitrary compositions, UTF-16 allows us to use several Unicode characters: the base character followed by one or many "mark" characters that "decorate" it.
+Để hỗ trợ các thành phần tùy ý, UTF-16 cho phép chúng tôi sử dụng một số ký tự Unicode: ký tự cơ sở theo sau là một hoặc nhiều ký tự "đánh dấu" "trang trí" cho nó.
-For instance, if we have `S` followed by the special "dot above" character (code `\u0307`), it is shown as Ṡ.
+Ví dụ: nếu chúng ta có `S` theo sau là ký tự "dấu chấm phía trên" đặc biệt (mã `\u0307`), thì nó được hiển thị là Ṡ.
```js run
alert( 'S\u0307' ); // Ṡ
```
-If we need an additional mark above the letter (or below it) -- no problem, just add the necessary mark character.
+Nếu chúng ta cần một dấu bổ sung phía trên chữ cái (hoặc bên dưới nó) -- không vấn đề gì, chỉ cần thêm ký tự dấu cần thiết.
-For instance, if we append a character "dot below" (code `\u0323`), then we'll have "S with dots above and below": `Ṩ`.
+Ví dụ: nếu chúng ta thêm một ký tự "dấu chấm bên dưới" (mã `\u0323`), thì chúng ta sẽ có "S có dấu chấm bên trên và bên dưới": `Ṩ`.
-For example:
+Ví dụ:
```js run
alert( 'S\u0307\u0323' ); // Ṩ
```
-This provides great flexibility, but also an interesting problem: two characters may visually look the same, but be represented with different Unicode compositions.
+Điều này mang lại sự linh hoạt tuyệt vời, nhưng cũng là một vấn đề thú vị: hai ký tự có thể trông giống nhau về mặt trực quan, nhưng được thể hiện bằng các thành phần Unicode khác nhau.
-For instance:
+Ví dụ:
```js run
-let s1 = 'S\u0307\u0323'; // Ṩ, S + dot above + dot below
-let s2 = 'S\u0323\u0307'; // Ṩ, S + dot below + dot above
+let s1 = 'S\u0307\u0323'; // Ṩ, S + chấm trên + chấm dưới
+let s2 = 'S\u0323\u0307'; // Ṩ, S + chấm trên + chấm dưới
alert( `s1: ${s1}, s2: ${s2}` );
-alert( s1 == s2 ); // false though the characters look identical (?!)
+alert( s1 == s2 ); // false mặc dù các ký tự trông giống hệt nhau (?!)
```
-To solve this, there exists a "Unicode normalization" algorithm that brings each string to the single "normal" form.
+Để giải quyết vấn đề này, tồn tại thuật toán "Chuẩn hóa Unicode" đưa mỗi chuỗi về dạng "bình thường" duy nhất.
-It is implemented by [str.normalize()](mdn:js/String/normalize).
+Nó được triển khai bởi [str.normalize()](mdn:js/String/normalize).
```js run
alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true
```
-It's funny that in our situation `normalize()` actually brings together a sequence of 3 characters to one: `\u1e68` (S with two dots).
+Thật buồn cười là trong tình huống của chúng ta, `normalize()` thực sự tập hợp một chuỗi gồm 3 ký tự thành một: `\u1e68` (S có hai dấu chấm).
```js run
alert( "S\u0307\u0323".normalize().length ); // 1
@@ -655,25 +653,25 @@ alert( "S\u0307\u0323".normalize().length ); // 1
alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
```
-In reality, this is not always the case. The reason being that the symbol `Ṩ` is "common enough", so UTF-16 creators included it in the main table and gave it the code.
+Trong thực tế, điều này không phải lúc nào cũng đúng. Lý do là ký hiệu `Ṩ` là "đủ phổ biến", vì vậy những người tạo UTF-16 đã đưa nó vào bảng chính và đặt mã cho nó.
-If you want to learn more about normalization rules and variants -- they are described in the appendix of the Unicode standard: [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/), but for most practical purposes the information from this section is enough.
+Nếu bạn muốn tìm hiểu thêm về các biến thể và quy tắc chuẩn hóa -- chúng được mô tả trong phần phụ lục của tiêu chuẩn Unicode: [Biểu mẫu chuẩn hóa Unicode](http://www.unicode.org/reports/tr15/), nhưng đối với hầu hết các trường hợp thực tế mục đích thông tin từ phần này là đủ.
-## Summary
+## Tóm tắt
-- There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions `${…}`.
-- Strings in JavaScript are encoded using UTF-16.
-- We can use special characters like `\n` and insert letters by their Unicode using `\u...`.
-- To get a character, use: `[]`.
-- To get a substring, use: `slice` or `substring`.
-- To lowercase/uppercase a string, use: `toLowerCase/toUpperCase`.
-- To look for a substring, use: `indexOf`, or `includes/startsWith/endsWith` for simple checks.
-- To compare strings according to the language, use: `localeCompare`, otherwise they are compared by character codes.
+- Có 3 loại trích dẫn. Backticks cho phép một chuỗi mở rộng trên nhiều dòng và nhúng các biểu thức `${…}`.
+- Các chuỗi trong JavaScript được mã hóa bằng UTF-16.
+- Chúng ta có thể sử dụng các ký tự đặc biệt như `\n` và chèn các chữ cái theo Unicode của chúng bằng cách sử dụng `\u...`.
+- Để lấy một ký tự, sử dụng: `[]`.
+- Để lấy chuỗi con, dùng: `slice` hoặc `substring`.
+- Để viết thường/viết hoa một chuỗi, sử dụng: `toLowerCase/toUpperCase`.
+- Để tìm một chuỗi con, hãy sử dụng: `indexOf`, hoặc `includes/startsWith/endsWith` để kiểm tra đơn giản.
+- Để so sánh các chuỗi theo ngôn ngữ, hãy sử dụng: `localeCompare`, nếu không thì chúng được so sánh bằng mã ký tự.
-There are several other helpful methods in strings:
+Có một số phương pháp hữu ích khác trong chuỗi:
-- `str.trim()` -- removes ("trims") spaces from the beginning and end of the string.
-- `str.repeat(n)` -- repeats the string `n` times.
-- ...and more to be found in the [manual](mdn:js/String).
+- `str.trim()` -- xóa khoảng trắng ("trims") khỏi đầu và cuối chuỗi.
+- `str.repeat(n)` -- lặp lại chuỗi `n` lần.
+- ...và nhiều hơn nữa được tìm thấy trong [hướng dẫn sử dụng](mdn:js/String).
-Strings also have methods for doing search/replace with regular expressions. But that's big topic, so it's explained in a separate tutorial section .
+Các chuỗi cũng có các phương thức để thực hiện tìm kiếm/thay thế bằng các biểu thức thông thường. Nhưng đó là chủ đề lớn nên nó được giải thích trong phần hướng dẫn riêng biệt .
From faad5b06045602ed3123b2fd2f84a841c82a3f05 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:14:53 +0700
Subject: [PATCH 05/13] Update task.md
---
1-js/05-data-types/03-string/1-ucfirst/task.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/1-js/05-data-types/03-string/1-ucfirst/task.md b/1-js/05-data-types/03-string/1-ucfirst/task.md
index ed8a1e6a7..2ef43243f 100644
--- a/1-js/05-data-types/03-string/1-ucfirst/task.md
+++ b/1-js/05-data-types/03-string/1-ucfirst/task.md
@@ -2,9 +2,9 @@ importance: 5
---
-# Uppercase the first character
+# Chữ hoa ký tự đầu tiên
-Write a function `ucFirst(str)` that returns the string `str` with the uppercased first character, for instance:
+Ví dụ, viết hàm `ucFirst(str)` trả về chuỗi `str` với ký tự đầu tiên được viết hoa:
```js
ucFirst("john") == "John";
From 66f4a9d856d0ac2d7a7cfd3cbd9a133d69cdad34 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:15:37 +0700
Subject: [PATCH 06/13] Update solution.md
---
1-js/05-data-types/03-string/1-ucfirst/solution.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/1-js/05-data-types/03-string/1-ucfirst/solution.md b/1-js/05-data-types/03-string/1-ucfirst/solution.md
index f7a332d0d..5ab8c7f2c 100644
--- a/1-js/05-data-types/03-string/1-ucfirst/solution.md
+++ b/1-js/05-data-types/03-string/1-ucfirst/solution.md
@@ -1,19 +1,19 @@
-We can't "replace" the first character, because strings in JavaScript are immutable.
+Chúng ta không thể "thay thế" ký tự đầu tiên, bởi vì các chuỗi trong JavaScript là bất biến.
-But we can make a new string based on the existing one, with the uppercased first character:
+Nhưng chúng ta có thể tạo một chuỗi mới dựa trên chuỗi hiện có, với ký tự đầu tiên được viết hoa:
```js
let newStr = str[0].toUpperCase() + str.slice(1);
```
-There's a small problem though. If `str` is empty, then `str[0]` is `undefined`, and as `undefined` doesn't have the `toUpperCase()` method, we'll get an error.
+Có một vấn đề nhỏ mặc dù. Nếu `str` trống, thì `str[0]` là `undefined` và vì `undefined` không có phương thức `toUpperCase()` nên chúng ta sẽ gặp lỗi.
-There are two variants here:
+Có hai biến thể ở đây:
-1. Use `str.charAt(0)`, as it always returns a string (maybe empty).
-2. Add a test for an empty string.
+1. Sử dụng `str.charAt(0)`, vì nó luôn trả về một chuỗi (có thể trống).
+2. Thêm kiểm tra cho chuỗi trống.
-Here's the 2nd variant:
+Đây là biến thể thứ 2:
```js run demo
function ucFirst(str) {
From c38276eee5bddabd29cd42a9586a9f07da48a7e3 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:16:27 +0700
Subject: [PATCH 07/13] Update task.md
---
1-js/05-data-types/03-string/2-check-spam/task.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/1-js/05-data-types/03-string/2-check-spam/task.md b/1-js/05-data-types/03-string/2-check-spam/task.md
index 98b5dd8a0..d2765d7ee 100644
--- a/1-js/05-data-types/03-string/2-check-spam/task.md
+++ b/1-js/05-data-types/03-string/2-check-spam/task.md
@@ -2,11 +2,11 @@ importance: 5
---
-# Check for spam
+# Kiểm tra spam
-Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise `false`.
+Viết hàm `checkSpam(str)` trả về `true` nếu `str` chứa 'viagra' hoặc 'XXX', nếu không thì `false`.
-The function must be case-insensitive:
+Hàm phải phân biệt chữ hoa chữ thường:
```js
checkSpam('buy ViAgRA now') == true
From a9aa74896f634c826aa01dccde3d197d8bae5056 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:16:50 +0700
Subject: [PATCH 08/13] Update solution.md
---
1-js/05-data-types/03-string/2-check-spam/solution.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/1-js/05-data-types/03-string/2-check-spam/solution.md b/1-js/05-data-types/03-string/2-check-spam/solution.md
index de8dde57d..fb20c49c9 100644
--- a/1-js/05-data-types/03-string/2-check-spam/solution.md
+++ b/1-js/05-data-types/03-string/2-check-spam/solution.md
@@ -1,4 +1,4 @@
-To make the search case-insensitive, let's bring the string to lower case and then search:
+Để làm cho tìm kiếm không phân biệt chữ hoa chữ thường, hãy chuyển chuỗi thành chữ thường và sau đó tìm kiếm:
```js run demo
function checkSpam(str) {
From d62242fa1dfc0cf69dd8cfd38398d807dee6a2cd Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:18:41 +0700
Subject: [PATCH 09/13] Update task.md
---
1-js/05-data-types/03-string/3-truncate/task.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/1-js/05-data-types/03-string/3-truncate/task.md b/1-js/05-data-types/03-string/3-truncate/task.md
index 6382029f4..4f6e78367 100644
--- a/1-js/05-data-types/03-string/3-truncate/task.md
+++ b/1-js/05-data-types/03-string/3-truncate/task.md
@@ -2,13 +2,13 @@ importance: 5
---
-# Truncate the text
+# Cắt bớt văn bản
-Create a function `truncate(str, maxlength)` that checks the length of the `str` and, if it exceeds `maxlength` -- replaces the end of `str` with the ellipsis character `"…"`, to make its length equal to `maxlength`.
+Tạo một hàm `truncate(str, maxlength)` để kiểm tra độ dài của `str` và, nếu nó vượt quá `maxlength` -- thay thế phần cuối của `str` bằng ký tự dấu chấm lửng `"…"`, để tạo chiều dài bằng `maxlength`.
-The result of the function should be the truncated (if needed) string.
+Kết quả của hàm phải là chuỗi bị cắt ngắn (nếu cần).
-For instance:
+Ví dụ:
```js
truncate("What I'd like to tell on this topic is:", 20) = "What I'd like to te…"
From 7efe67a595a8d6f30ce2007d31e601c8439baa53 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:19:04 +0700
Subject: [PATCH 10/13] Update solution.md
---
1-js/05-data-types/03-string/3-truncate/solution.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/1-js/05-data-types/03-string/3-truncate/solution.md b/1-js/05-data-types/03-string/3-truncate/solution.md
index d51672ae6..e54fab7bf 100644
--- a/1-js/05-data-types/03-string/3-truncate/solution.md
+++ b/1-js/05-data-types/03-string/3-truncate/solution.md
@@ -1,6 +1,6 @@
-The maximal length must be `maxlength`, so we need to cut it a little shorter, to give space for the ellipsis.
+Độ dài tối đa phải là `maxlength`, vì vậy chúng ta cần cắt nó ngắn hơn một chút để tạo khoảng trống cho dấu chấm lửng.
-Note that there is actually a single Unicode character for an ellipsis. That's not three dots.
+Lưu ý rằng thực tế có một ký tự Unicode duy nhất cho dấu chấm lửng. Đó không phải là ba chấm.
```js run demo
function truncate(str, maxlength) {
From c60acc1f0bfdda029cc1d87644b9a32d36c78fdc Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:19:40 +0700
Subject: [PATCH 11/13] Update task.md
---
1-js/05-data-types/03-string/4-extract-currency/task.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/1-js/05-data-types/03-string/4-extract-currency/task.md b/1-js/05-data-types/03-string/4-extract-currency/task.md
index feb16e642..0f397fe5f 100644
--- a/1-js/05-data-types/03-string/4-extract-currency/task.md
+++ b/1-js/05-data-types/03-string/4-extract-currency/task.md
@@ -2,13 +2,13 @@ importance: 4
---
-# Extract the money
+# Trích xuất tiền
-We have a cost in the form `"$120"`. That is: the dollar sign goes first, and then the number.
+Chúng ta có chi phí ở dạng `"$120"`. Đó là: ký hiệu đô la đi trước, sau đó là số.
-Create a function `extractCurrencyValue(str)` that would extract the numeric value from such string and return it.
+Tạo một hàm `extractCurrencyValue(str)` sẽ trích xuất giá trị số từ chuỗi đó và trả về giá trị đó.
-The example:
+Ví dụ:
```js
alert( extractCurrencyValue('$120') === 120 ); // true
From 46401abf023efa48b52b5d4a776aa192feeb9645 Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Thu, 8 Jun 2023 15:53:32 +0700
Subject: [PATCH 12/13] sync with en version
---
1-js/05-data-types/03-string/article.md | 256 +++++-------------------
1 file changed, 50 insertions(+), 206 deletions(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index 7a6517250..c872911b3 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -48,9 +48,9 @@ let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John";
```
-Dấu ngoặc đơn và dấu ngoặc kép xuất hiện từ thời cổ đại khi tạo ngôn ngữ khi nhu cầu về chuỗi nhiều dòng không được tính đến. Backticks xuất hiện muộn hơn nhiều và do đó linh hoạt hơn.
+Dấu ngoặc đơn và dấu ngoặc kép xuất hiện từ thời cổ đại khi tạo ngôn ngữ, khi nhu cầu về chuỗi nhiều dòng không được tính đến. Backticks xuất hiện muộn hơn nhiều và do đó linh hoạt hơn.
-Backticks cũng cho phép chúng ta chỉ định một "hàm mẫu" trước backtick đầu tiên. Cú pháp là: func`string`. Hàm `func` được gọi tự động, nhận chuỗi và các biểu thức được nhúng và có thể xử lý chúng. Đây được gọi là "mẫu được gắn thẻ". Tính năng này giúp triển khai tạo khuôn mẫu tùy chỉnh dễ dàng hơn nhưng hiếm khi được sử dụng trong thực tế. Bạn có thể đọc thêm về nó trong [hướng dẫn sử dụng](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).
+Backticks cũng cho phép chúng ta chỉ định một "hàm mẫu" trước backtick đầu tiên. Cú pháp là: func`string`. Hàm `func` được gọi tự động, nhận chuỗi và các biểu thức được nhúng và có thể xử lý chúng. Tính năng này được gọi là "mẫu được gắn thẻ", nó hiếm khi được nhìn thấy, nhưng bạn có thể đọc về nó trong MDN: [Template literals](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).
## Ký tự đặc biệt
@@ -59,10 +59,10 @@ Vẫn có thể tạo chuỗi nhiều dòng với dấu nháy đơn và kép b
```js run
let guestList = "Guests:\n * John\n * Pete\n * Mary";
-alert(guestList); // một danh sách khách nhiều dòng
+alert(guestList); // một danh sách khách nhiều dòng, giống như trên
```
-Ví dụ, hai dòng này bằng nhau, nhưng viết khác nhau:
+Như một ví dụ đơn giản hơn, hai dòng này bằng nhau, chỉ được viết khác nhau:
```js run
let str1 = "Hello\nWorld"; // hai dòng sử dụng một "ký tự dòng mới"
@@ -74,33 +74,26 @@ World`;
alert(str1 == str2); // true
```
-Có những ký tự "đặc biệt" khác, ít phổ biến hơn.
-
-Đây là danh sách đầy đủ:
+Có các ký tự đặc biệt khác, ít phổ biến hơn:
| Nhân vật | Mô tả |
|--------|-------------|
|`\n`|Dòng mới|
-|`\r`|Trở về đầu hàng: không được sử dụng một mình. Các tệp văn bản Windows sử dụng kết hợp hai ký tự `\r\n` để biểu thị ngắt dòng. |
-|`\'`, `\"`|Trích dẫn|
+|`\r`|Trong các tệp văn bản Windows, sự kết hợp của hai ký tự `\r\n` biểu thị một ngắt mới, trong khi trên hệ điều hành không phải Windows, nó chỉ là `\n`. Đó là vì lý do lịch sử, hầu hết các phần mềm Windows cũng hiểu `\n`. |
+|`\'`, `\"`, \\`|Trích dẫn|
|`\\`|Dấu gạch chéo ngược|
|`\t`|Tab|
-|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- được giữ lại để tương thích, không được sử dụng hiện nay. |
-|`\xXX`|Ký tự Unicode với Unicode thập lục phân đã cho `XX`, ví dụ: `'\x7A'` giống như `'z'`.|
-|`\uXXXX`|Một ký hiệu Unicode có mã hex `XXXX` trong mã hóa UTF-16, ví dụ `\u00A9` -- là một ký hiệu Unicode cho ký hiệu bản quyền `©`. Nó phải có chính xác 4 chữ số hex. |
-|`\u{X…XXXXXX}` (1 đến 6 ký tự hex)|Ký hiệu Unicode với mã hóa UTF-32 nhất định. Một số ký tự hiếm được mã hóa bằng hai ký hiệu Unicode, chiếm 4 byte. Bằng cách này, chúng ta có thể chèn mã dài. |
+|`\b`, `\f`, `\v`| Backspace, Form Feed, Tab Dọc -- nhắc đến cho đầy đủ, có từ xưa, nay không dùng (có thể quên ngay)). |
+
+Như bạn có thể thấy, tất cả các ký tự đặc biệt đều bắt đầu bằng ký tự gạch chéo ngược `\`. Nó còn được gọi là "ký tự thoát".
-Ví dụ với Unicode:
+Bởi vì nó rất đặc biệt, nên nếu chúng ta cần hiển thị dấu gạch chéo ngược `\` thực sự trong chuỗi, chúng ta cần nhân đôi nó:
```js run
-alert( "\u00A9" ); // ©
-alert( "\u{20331}" ); // 佫, một chữ tượng hình hiếm của Trung Quốc (mã Unicode dài)
-alert( "\u{1F60D}" ); // 😍, một biểu tượng khuôn mặt tươi cười (một mã Unicode dài khác)
+alert( `Dấu gạch chéo ngược: \\` ); // Dấu gạch chéo ngược: \
```
-Tất cả các ký tự đặc biệt đều bắt đầu bằng ký tự gạch chéo ngược `\`. Nó còn được gọi là "ký tự thoát".
-
-Chúng ta cũng có thể sử dụng nó nếu chúng ta muốn chèn một trích dẫn vào chuỗi.
+Cái gọi là trích dẫn "thoát" `\'`, `\"`, \\` được sử dụng để chèn một trích dẫn vào cùng một chuỗi được trích dẫn.
Ví dụ:
@@ -113,18 +106,10 @@ Như bạn có thể thấy, chúng ta phải thêm vào trước trích dẫn b
Tất nhiên, chỉ những trích dẫn giống với những trích dẫn kèm theo mới cần được thoát. Vì vậy, như một giải pháp tao nhã hơn, thay vào đó, chúng ta có thể chuyển sang dấu ngoặc kép hoặc dấu nháy ngược:
```js run
-alert( `I'm the Walrus!` ); // I'm the Walrus!
+alert( "I'm the Walrus!" ); // I'm the Walrus!
```
-Lưu ý rằng dấu gạch chéo ngược `\` phục vụ cho việc đọc chính xác chuỗi bằng JavaScript, sau đó biến mất. Chuỗi trong bộ nhớ không có `\`. Bạn có thể thấy rõ điều đó trong `alert` từ các ví dụ ở trên.
-
-Nhưng nếu chúng ta cần hiển thị dấu gạch chéo ngược `\` trong chuỗi thì sao?
-
-Điều đó là có thể, nhưng chúng ta cần nhân đôi nó như `\\`:
-
-```js run
-alert( `The backslash: \\` ); // Dấu gạch chéo ngược: \
-```
+Bên cạnh những ký tự đặc biệt này, còn có một ký hiệu đặc biệt cho mã Unicode `\u…`, ký hiệu này hiếm khi được sử dụng và được trình bày trong chương tùy chọn về [Unicode](info:unicode).
## Chiều dài chuỗi
@@ -139,40 +124,43 @@ Lưu ý rằng `\n` là một ký tự "đặc biệt", vì vậy độ dài th
```warn header="`length` là thuộc tính"
Những người có kiến thức cơ bản về một số ngôn ngữ khác đôi khi gõ nhầm bằng cách gọi `str.length()` thay vì chỉ `str.length`. Điều đó không hiệu quả.
-Hãy lưu ý rằng `str.length` là thuộc tính số, không phải hàm. Không cần thêm dấu ngoặc đơn sau nó.
+Hãy lưu ý rằng `str.length` là thuộc tính số, không phải hàm. Không cần thêm dấu ngoặc đơn sau nó. Không phải `.length()`, mà là `.length`.
```
## Truy cập ký tự
-Để lấy một ký tự ở vị trí `pos`, hãy sử dụng dấu ngoặc vuông `[pos]` hoặc gọi phương thức [str.charAt(pos)](mdn:js/String/charAt). Ký tự đầu tiên bắt đầu từ vị trí số 0:
+Để lấy một ký tự ở vị trí `pos`, hãy sử dụng dấu ngoặc vuông `[pos]` hoặc gọi phương thức [str.at(pos)](mdn:js/String/at). Ký tự đầu tiên bắt đầu từ vị trí số 0:
```js run
-let str = `Hello`;
+let str = `Xin chào`;
// ký tự đầu tiên
-alert( str[0] ); // H
-alert( str.charAt(0) ); // H
+alert( str[0] ); // X
+alert( str.at(0) ); // X
-// the last character
+// ký tự cuối cùng
alert( str[str.length - 1] ); // o
+alert( str.at(-1) );
```
-Dấu ngoặc vuông là một cách hiện đại để lấy một ký tự, trong khi `charAt` chủ yếu tồn tại vì lý do lịch sử.
+Như bạn có thể thấy, phương thức `.at(pos)` có lợi ích là cho phép vị trí âm. Nếu `pos` là số âm, thì nó được tính từ cuối chuỗi.
+
+Vì vậy, `.at(-1)` có nghĩa là ký tự cuối cùng và `.at(-2)` là ký tự trước nó, v.v.
-Sự khác biệt duy nhất giữa chúng là nếu không tìm thấy ký tự nào, `[]` trả về `undefined`, và `charAt` trả về một chuỗi rỗng:
+Ví dụ: dấu ngoặc vuông luôn trả về `undefined` cho các chỉ mục phủ định:
```js run
let str = `Xin chào`;
-alert( str[1000] ); // undefined
-alert( str.charAt(1000) ); // '' (một chuỗi rỗng)
+alert( str[-2] ); // undefined
+alert( str.at(-2) ); // 'à'
```
Chúng ta cũng có thể lặp lại các ký tự bằng cách sử dụng `for..of`:
```js run
-for (let char of "Hello") {
- alert(char); // H,e,l,l,o (char trở thành "H", rồi "e", rồi "l", v.v.)
+for (let char of "Xin chào") {
+ alert(char); // X,i,n, ,c,h,à,o (char trở thành "X", rồi "i", rồi "n", v.v.)
}
```
@@ -214,7 +202,7 @@ alert( 'Interface'.toLowerCase() ); // Interface
Hoặc, nếu chúng ta muốn một ký tự được viết thường:
-```js
+```js run
alert( 'Interface'[0].toLowerCase() ); // 'i'
```
@@ -310,45 +298,6 @@ if (str.indexOf("Widget") != -1) {
}
```
-#### Thủ thuật KHÔNG theo bit
-
-Một trong những thủ thuật cũ được sử dụng ở đây là toán tử [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) `~`. Nó chuyển đổi số thành số nguyên 32 bit (loại bỏ phần thập phân nếu có) và sau đó đảo ngược tất cả các bit trong biểu diễn nhị phân của nó.
-
-Trong thực tế, điều đó có nghĩa là một điều đơn giản: đối với số nguyên 32 bit `~n` bằng `-(n+1)`.
-
-Ví dụ:
-
-```js run
-alert( ~2 ); // -3, giống như -(2+1)
-alert( ~1 ); // -2, giống như -(1+1)
-alert( ~0 ); // -1, giống như -(0+1)
-*!*
-alert( ~-1 ); // 0, giống như -(-1+1)
-*/!*
-```
-
-Như chúng ta có thể thấy, `~n` chỉ bằng 0 nếu `n == -1` (đó là đối với bất kỳ số nguyên có dấu 32 bit nào `n`).
-
-Vì vậy, phép thử `if ( ~str.indexOf("...") )` chỉ đúng nếu kết quả của `indexOf` không phải là `-1`. Nói cách khác, khi có một sự trùng khớp.
-
-Mọi người sử dụng nó để rút ngắn kiểm tra `indexOf`:
-
-```js run
-let str = "Widget";
-
-if (~str.indexOf("Widget")) {
- alert( 'Đã tìm thấy nó·!' ); // hoạt động
-}
-```
-
-Thông thường không nên sử dụng các tính năng ngôn ngữ theo cách không rõ ràng, nhưng thủ thuật cụ thể này được sử dụng rộng rãi trong mã cũ, vì vậy chúng ta nên hiểu nó.
-
-Chỉ cần nhớ: `if (~str.indexOf(...))` đọc là "nếu tìm thấy".
-
-Tuy nhiên, nói một cách chính xác, vì các số lớn bị cắt bớt thành 32 bit bởi toán tử `~`, nên tồn tại các số khác cho `0`, số nhỏ nhất là `~4294967295=0`. Điều đó làm cho kiểm tra như vậy chỉ chính xác nếu một chuỗi không dài.
-
-Hiện tại, chúng ta chỉ có thể thấy thủ thuật này trong mã cũ, vì JavaScript hiện đại cung cấp phương thức `.includes` (xem bên dưới).
-
### includes, startsWith, endsWith
Phương thức hiện đại hơn [str.includes(substr, pos)](mdn:js/String/includes) trả về `true/false` tùy thuộc vào việc `str` có chứa `substr` bên trong hay không.
@@ -371,8 +320,8 @@ alert( "Widget".includes("id", 3) ); // false, từ vị trí 3 không có "id"
Các phương thức [str.startsWith](mdn:js/String/startsWith) và [str.endsWith](mdn:js/String/endsWith) thực hiện chính xác những gì chúng nói:
```js run
-alert( "Widget".startsWith("Wid") ); // true, "Widget" bắt đầu bằng "Wid"
-alert( "Widget".endsWith("get") ); // true, "Widget" kết thúc bằng "get"
+alert( "*!*Wid*/!*get".startsWith("Wid") ); // true, "Widget" bắt đầu bằng "Wid"
+alert( "Wid*!*get*/!*".endsWith("get") ); // true, "Widget" kết thúc bằng "get"
```
## Lấy một chuỗi con
@@ -407,7 +356,7 @@ Có 3 phương thức trong JavaScript để lấy chuỗi con: `substring`, `su
```
`str.substring(start [, end])`
-: Trả về một phần của chuỗi *giữa* `start` và `end`.
+: Trả về một phần của chuỗi *giữa* `start` và `end` (không bao gồm lớn hơn của chúng).
Điều này gần giống với `slice`, nhưng nó cho phép `start` lớn hơn `end`.
@@ -444,19 +393,22 @@ Có 3 phương thức trong JavaScript để lấy chuỗi con: `substring`, `su
let str = "strin*!*gi*/!*fy";
alert( str.substr(-4, 2) ); // 'gi', từ vị trí thứ 4 lấy 2 ký tự
```
+ Phương pháp này nằm trong [Phụ lục B](https://tc39.es/ecma262/#sec-string.prototype.substr) của đặc điểm kỹ thuật ngôn ngữ. Điều đó có nghĩa là chỉ các JavaScript engine được lưu trữ trên trình duyệt mới hỗ trợ nó, và nó không được đề nghị sử dụng. Trong thực tế, nó được hỗ trợ ở khắp mọi nơi.
Hãy tóm tắt lại các phương pháp này để tránh nhầm lẫn:
| phương pháp | chọn... | âm bản |
|---|------------|--------|
| `slice(start, end)` | từ `start` đến `end` (không bao gồm `end`) | cho phép số âm |
-| `substring(start, end)` | giữa `start` và `end` | giá trị âm có nghĩa là `0` |
+| `substring(start, end)` | giữa `start` và `end` (không bao gồm `end`)| giá trị âm có nghĩa là `0` |
| `substr(start, length)` | từ `start` lấy các ký tự `length` | cho phép `start` âm |
```smart header="Chọn cái nào?"
Tất cả chúng có thể làm công việc. Về mặt hình thức, `substr` có một nhược điểm nhỏ: nó không được mô tả trong thông số kỹ thuật JavaScript cốt lõi mà trong Phụ lục B, bao gồm các tính năng chỉ dành cho trình duyệt tồn tại chủ yếu vì lý do lịch sử. Vì vậy, các môi trường không có trình duyệt có thể không hỗ trợ nó. Nhưng trong thực tế, nó hoạt động ở mọi nơi.
-Trong số hai biến thể còn lại, `slice` linh hoạt hơn một chút, nó cho phép đối số âm và viết ngắn hơn. Vì vậy, chỉ cần nhớ `slice` của ba phương pháp này là đủ.
+Trong số hai biến thể còn lại, `slice` linh hoạt hơn một chút, nó cho phép đối số âm và viết ngắn hơn.
+
+Vì vậy, để sử dụng thực tế, chỉ cần nhớ `slice` là đủ.
```
## So sánh chuỗi
@@ -479,17 +431,18 @@ Mặc dù, có một số điều kỳ lạ.
Điều này có thể dẫn đến kết quả lạ nếu chúng ta sắp xếp các tên quốc gia này. Thông thường mọi người sẽ mong đợi `Zealand` sẽ đứng sau `Österreich` trong danh sách.
-Để hiểu điều gì xảy ra, hãy xem lại biểu diễn bên trong của chuỗi trong JavaScript.
+Để hiểu điều gì sẽ xảy ra, chúng ta nên biết rằng các chuỗi trong Javascript được mã hóa bằng [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Đó là: mỗi ký tự có một mã số tương ứng.
-Tất cả các chuỗi được mã hóa bằng [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Đó là: mỗi ký tự có một mã số tương ứng. Có những phương pháp đặc biệt cho phép lấy ký tự cho mã và ngược lại.
+Có các phương thức đặc biệt cho phép lấy ký tự cho mã và ngược lại:
`str.codePointAt(pos)`
-: Trả về mã cho ký tự tại vị trí `pos`:
+: Trả về một số thập phân biểu thị mã cho ký tự ở vị trí `pos`:
```js run
// các chữ cái viết hoa và viết thường có mã khác nhau
- alert( "z".codePointAt(0) ); // 122
alert( "Z".codePointAt(0) ); // 90
+ alert( "z".codePointAt(0) ); // 122
+ alert( "z".codePointAt(0).toString(16) ); // 7a (nếu chúng ta cần một giá trị thập lục phân)
```
`String.fromCodePoint(code)`
@@ -497,13 +450,7 @@ Tất cả các chuỗi được mã hóa bằng [UTF-16](https://en.wikipedia.o
```js run
alert( String.fromCodePoint(90) ); // Z
- ```
-
- Chúng ta cũng có thể thêm các ký tự Unicode theo mã của chúng bằng cách sử dụng `\u` theo sau là mã hex:
-
- ```js run
- // 90 là 5a trong hệ thập lục phân
- alert( '\u005a' ); // Z
+ alert( String.fromCodePoint(0x5a) ); // Z (chúng ta cũng có thể sử dụng giá trị hex làm đối số)
```
Bây giờ, hãy xem các ký tự có mã `65..220` (bảng chữ cái Latinh và thêm một chút) bằng cách tạo một chuỗi gồm chúng:
@@ -515,6 +462,7 @@ for (let i = 65; i <= 220; i++) {
str += String.fromCodePoint(i);
}
alert( str );
+// Đầu ra:
// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
// ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ
```
@@ -534,7 +482,7 @@ Thuật toán "đúng" để thực hiện so sánh chuỗi phức tạp hơn v
Vì vậy, trình duyệt cần biết ngôn ngữ để so sánh.
-May mắn thay, tất cả các trình duyệt hiện đại (IE10- yêu cầu thư viện bổ sung [Intl.js](https://github.com/andyearnshaw/Intl.js/)) đều hỗ trợ tiêu chuẩn quốc tế hóa [ECMA-402](http://www. ecma-international.org/ecma-402/1.0/ECMA-402.pdf).
+May mắn thay, các trình duyệt hiện đại hỗ trợ tiêu chuẩn quốc tế hóa [ECMA-402](https://www.ecma-international.org/publications-and-standards/standards/ecma-402/).
Nó cung cấp một phương pháp đặc biệt để so sánh các chuỗi trong các ngôn ngữ khác nhau, tuân theo các quy tắc của chúng.
@@ -552,116 +500,10 @@ alert( 'Österreich'.localeCompare('Zealand') ); // -1
Phương thức này thực sự có hai đối số bổ sung được chỉ định trong [tài liệu](mdn:js/String/localeCompare), cho phép phương thức này chỉ định ngôn ngữ (theo mặc định được lấy từ môi trường, thứ tự chữ cái phụ thuộc vào ngôn ngữ) và thiết lập các quy tắc bổ sung như phân biệt chữ hoa chữ thường hoặc nên coi `"a"` và `"á"` như nhau, v.v.
-## Kiến thức nâng cao"
-Phần này đi sâu hơn vào bên trong chuỗi. Kiến thức này sẽ hữu ích cho bạn nếu bạn định xử lý biểu tượng cảm xúc, ký tự toán học hoặc chữ tượng hình hiếm hoặc các ký hiệu hiếm khác.
-
-Bạn có thể bỏ qua phần này nếu bạn không có kế hoạch hỗ trợ chúng.
-```
-
-### Cặp thay thế
-
-Tất cả các ký tự được sử dụng thường xuyên đều có mã 2 byte. Các chữ cái trong hầu hết các ngôn ngữ châu Âu, số và thậm chí hầu hết các chữ tượng hình đều có biểu diễn 2 byte.
-
-Nhưng 2 byte chỉ cho phép 65536 kết hợp và điều đó là không đủ cho mọi biểu tượng có thể. Vì vậy, các ký hiệu hiếm được mã hóa bằng một cặp ký tự 2 byte được gọi là "cặp thay thế".
-
-Độ dài của các ký hiệu như vậy là `2`:
-
-```js run
-alert( '𝒳'.length ); // 2, CHỮ VIẾT HOA TOÁN HỌC X
-alert( '😂'.length ); // 2, MẶT VỚI GIỌT NƯỚC MẮT VUI
-alert( '𩷶'.length ); // 2, một chữ tượng hình hiếm của Trung Quốc
-```
-
-Lưu ý rằng các cặp thay thế không tồn tại vào thời điểm JavaScript được tạo và do đó không được ngôn ngữ xử lý chính xác!
-
-Chúng ta thực sự có một ký hiệu duy nhất trong mỗi chuỗi ở trên, nhưng `độ dài` hiển thị độ dài `2`.
-
-`String.fromCodePoint` và `str.codePointAt` là một vài phương pháp hiếm hoi đối phó với các cặp thay thế đúng. Gần đây chúng đã xuất hiện trong ngôn ngữ. Trước chúng, đã chỉ có [String.fromCharCode](mdn:js/String/fromCharCode) và [str.charCodeAt](mdn:js/String/charCodeAt). Những phương pháp này thực sự giống như `fromCodePoint/codePointAt`, nhưng không hoạt động với các cặp thay thế.
-
-Lấy một biểu tượng có thể khó khăn, bởi vì các cặp thay thế được coi là hai ký tự:
-
-```js run
-alert( '𝒳'[0] ); // ký tự lạ...
-alert( '𝒳'[1] ); // ...các mảnh của cặp thay thế
-```
-
-Lưu ý rằng các phần của cặp thay thế không có ý nghĩa gì nếu không có nhau. Vì vậy, các cảnh báo trong ví dụ trên thực sự hiển thị rác.
-
-Về mặt kỹ thuật, các cặp thay thế cũng có thể được phát hiện bằng mã của chúng: nếu một ký tự có mã trong khoảng `0xd800..0xdbff`, thì đó là phần đầu tiên của cặp thay thế. Ký tự tiếp theo (phần thứ hai) phải có mã trong khoảng `0xdc00..0xdfff`. Các khoảng thời gian này được dành riêng cho các cặp thay thế theo tiêu chuẩn.
-
-Trong trường hợp trên:
-
-```js run
-// charCodeAt không nhận biết cặp thay thế, vì vậy nó cung cấp mã cho các bộ phận
-
-alert( '𝒳'.charCodeAt(0).toString(16) ); // d835, giữa 0xd800 và 0xdbff
-alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3, giữa 0xdc00 và 0xdfff
-```
-
-Bạn sẽ tìm thấy nhiều cách hơn để xử lý các cặp thay thế ở phần sau của chương . Có thể có những thư viện đặc biệt cho điều đó, nhưng không có gì đủ nổi tiếng để đề xuất ở đây.
-
-### Dấu phụ và chuẩn hóa
-
-Trong nhiều ngôn ngữ, có những ký hiệu bao gồm ký tự cơ sở có dấu ở trên/dưới ký tự đó.
-
-Chẳng hạn, chữ `a` có thể là ký tự cơ sở cho: `àáâäãåā`. Hầu hết các ký tự "tổng hợp" phổ biến đều có mã riêng trong bảng UTF-16. Nhưng không phải tất cả chúng, bởi vì có quá nhiều kết hợp có thể.
-
-Để hỗ trợ các thành phần tùy ý, UTF-16 cho phép chúng tôi sử dụng một số ký tự Unicode: ký tự cơ sở theo sau là một hoặc nhiều ký tự "đánh dấu" "trang trí" cho nó.
-
-Ví dụ: nếu chúng ta có `S` theo sau là ký tự "dấu chấm phía trên" đặc biệt (mã `\u0307`), thì nó được hiển thị là Ṡ.
-
-```js run
-alert( 'S\u0307' ); // Ṡ
-```
-
-Nếu chúng ta cần một dấu bổ sung phía trên chữ cái (hoặc bên dưới nó) -- không vấn đề gì, chỉ cần thêm ký tự dấu cần thiết.
-
-Ví dụ: nếu chúng ta thêm một ký tự "dấu chấm bên dưới" (mã `\u0323`), thì chúng ta sẽ có "S có dấu chấm bên trên và bên dưới": `Ṩ`.
-
-Ví dụ:
-
-```js run
-alert( 'S\u0307\u0323' ); // Ṩ
-```
-
-Điều này mang lại sự linh hoạt tuyệt vời, nhưng cũng là một vấn đề thú vị: hai ký tự có thể trông giống nhau về mặt trực quan, nhưng được thể hiện bằng các thành phần Unicode khác nhau.
-
-Ví dụ:
-
-```js run
-let s1 = 'S\u0307\u0323'; // Ṩ, S + chấm trên + chấm dưới
-let s2 = 'S\u0323\u0307'; // Ṩ, S + chấm trên + chấm dưới
-
-alert( `s1: ${s1}, s2: ${s2}` );
-
-alert( s1 == s2 ); // false mặc dù các ký tự trông giống hệt nhau (?!)
-```
-
-Để giải quyết vấn đề này, tồn tại thuật toán "Chuẩn hóa Unicode" đưa mỗi chuỗi về dạng "bình thường" duy nhất.
-
-Nó được triển khai bởi [str.normalize()](mdn:js/String/normalize).
-
-```js run
-alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true
-```
-
-Thật buồn cười là trong tình huống của chúng ta, `normalize()` thực sự tập hợp một chuỗi gồm 3 ký tự thành một: `\u1e68` (S có hai dấu chấm).
-
-```js run
-alert( "S\u0307\u0323".normalize().length ); // 1
-
-alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
-```
-
-Trong thực tế, điều này không phải lúc nào cũng đúng. Lý do là ký hiệu `Ṩ` là "đủ phổ biến", vì vậy những người tạo UTF-16 đã đưa nó vào bảng chính và đặt mã cho nó.
-
-Nếu bạn muốn tìm hiểu thêm về các biến thể và quy tắc chuẩn hóa -- chúng được mô tả trong phần phụ lục của tiêu chuẩn Unicode: [Biểu mẫu chuẩn hóa Unicode](http://www.unicode.org/reports/tr15/), nhưng đối với hầu hết các trường hợp thực tế mục đích thông tin từ phần này là đủ.
-
## Tóm tắt
- Có 3 loại trích dẫn. Backticks cho phép một chuỗi mở rộng trên nhiều dòng và nhúng các biểu thức `${…}`.
-- Các chuỗi trong JavaScript được mã hóa bằng UTF-16.
-- Chúng ta có thể sử dụng các ký tự đặc biệt như `\n` và chèn các chữ cái theo Unicode của chúng bằng cách sử dụng `\u...`.
+- Chúng ta có thể sử dụng các ký tự đặc biệt, chẳng hạn như ngắt dòng `\n`.
- Để lấy một ký tự, sử dụng: `[]`.
- Để lấy chuỗi con, dùng: `slice` hoặc `substring`.
- Để viết thường/viết hoa một chuỗi, sử dụng: `toLowerCase/toUpperCase`.
@@ -675,3 +517,5 @@ Có một số phương pháp hữu ích khác trong chuỗi:
- ...và nhiều hơn nữa được tìm thấy trong [hướng dẫn sử dụng](mdn:js/String).
Các chuỗi cũng có các phương thức để thực hiện tìm kiếm/thay thế bằng các biểu thức thông thường. Nhưng đó là chủ đề lớn nên nó được giải thích trong phần hướng dẫn riêng biệt .
+
+Ngoài ra, hiện tại, điều quan trọng cần biết là các chuỗi dựa trên mã hóa Unicode và do đó, có vấn đề khi so sánh. Có thêm thông tin về Unicode trong chương .
From 681116e74452c46aa62b805ee7b23453efcd43bf Mon Sep 17 00:00:00 2001
From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com>
Date: Thu, 8 Jun 2023 15:54:27 +0700
Subject: [PATCH 13/13] Update article.md
---
1-js/05-data-types/03-string/article.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index c872911b3..c824f12ac 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -504,7 +504,7 @@ Phương thức này thực sự có hai đối số bổ sung được chỉ đ
- Có 3 loại trích dẫn. Backticks cho phép một chuỗi mở rộng trên nhiều dòng và nhúng các biểu thức `${…}`.
- Chúng ta có thể sử dụng các ký tự đặc biệt, chẳng hạn như ngắt dòng `\n`.
-- Để lấy một ký tự, sử dụng: `[]`.
+- Để lấy một ký tự, sử dụng: `[]` hay phương thức `at`.
- Để lấy chuỗi con, dùng: `slice` hoặc `substring`.
- Để viết thường/viết hoa một chuỗi, sử dụng: `toLowerCase/toUpperCase`.
- Để tìm một chuỗi con, hãy sử dụng: `indexOf`, hoặc `includes/startsWith/endsWith` để kiểm tra đơn giản.