diff --git a/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js b/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js index 490f570ad..a4b034cdd 100644 --- a/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js +++ b/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js @@ -1,10 +1,10 @@ function camelize(str) { return str - .split('-') // splits 'my-long-word' into array ['my', 'long', 'word'] + .split('-') // tách 'my-long-word' thành array ['my', 'long', 'word'] .map( - // capitalizes first letters of all array items except the first one - // converts ['my', 'long', 'word'] into ['my', 'Long', 'Word'] + // viết hoa các chữ cái đầu tiên của tất cả các phần tử array ngoại trừ phần tử đầu tiên + // chuyển ['my', 'long', 'word'] thành ['my', 'Long', 'Word'] (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1) ) - .join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord' + .join(''); // nối ['my', 'Long', 'Word'] thành 'myLongWord' } diff --git a/1-js/05-data-types/05-array-methods/1-camelcase/task.md b/1-js/05-data-types/05-array-methods/1-camelcase/task.md index ef5944636..f1bc85cdb 100644 --- a/1-js/05-data-types/05-array-methods/1-camelcase/task.md +++ b/1-js/05-data-types/05-array-methods/1-camelcase/task.md @@ -2,13 +2,13 @@ importance: 5 --- -# Translate border-left-width to borderLeftWidth +# Dịch border-left-width sang borderLeftWidth -Write the function `camelize(str)` that changes dash-separated words like "my-short-string" into camel-cased "myShortString". +Viết hàm `camelize(str)` để thay đổi các từ được phân tách bằng dấu gạch ngang như "my-short-string" thành "myShortString" có viết hoa. -That is: removes all dashes, each word after dash becomes uppercased. +Đó là: loại bỏ tất cả các dấu gạch ngang, mỗi từ sau dấu gạch ngang sẽ được viết hoa. -Examples: +Ví dụ: ```js camelize("background-color") == 'backgroundColor'; @@ -16,4 +16,4 @@ camelize("list-style-image") == 'listStyleImage'; camelize("-webkit-transition") == 'WebkitTransition'; ``` -P.S. Hint: use `split` to split the string into an array, transform it and `join` back. +Tái bút: Gợi ý: sử dụng `split` để chia chuỗi thành một array, biến đổi nó và `join` trở lại. diff --git a/1-js/05-data-types/05-array-methods/10-average-age/task.md b/1-js/05-data-types/05-array-methods/10-average-age/task.md index bf5f85df3..205f58690 100644 --- a/1-js/05-data-types/05-array-methods/10-average-age/task.md +++ b/1-js/05-data-types/05-array-methods/10-average-age/task.md @@ -2,13 +2,13 @@ importance: 4 --- -# Get average age +# Lấy tuổi trung bình -Write the function `getAverageAge(users)` that gets an array of objects with property `age` and returns the average age. +Viết hàm `getAverageAge(users)` để lấy một array các đối tượng có thuộc tính `age` và trả về tuổi trung bình. -The formula for the average is `(age1 + age2 + ... + ageN) / N`. +Công thức tính trung bình là `(age1 + age2 + ... + ageN) / N`. -For instance: +Ví dụ: ```js no-beautify let john = { name: "John", age: 25 }; diff --git a/1-js/05-data-types/05-array-methods/11-array-unique/solution.md b/1-js/05-data-types/05-array-methods/11-array-unique/solution.md index b9d627a0a..02de7057d 100644 --- a/1-js/05-data-types/05-array-methods/11-array-unique/solution.md +++ b/1-js/05-data-types/05-array-methods/11-array-unique/solution.md @@ -1,6 +1,6 @@ -Let's walk the array items: -- For each item we'll check if the resulting array already has that item. -- If it is so, then ignore, otherwise add to results. +Hãy đi qua các item array: +- Đối với mỗi item, chúng ta sẽ kiểm tra xem kết quả array đã có item đó chưa. +- Nếu đúng thì bỏ qua, nếu không thì cộng vào kết quả. ```js run demo function unique(arr) { @@ -22,18 +22,18 @@ let strings = ["Hare", "Krishna", "Hare", "Krishna", alert( unique(strings) ); // Hare, Krishna, :-O ``` -The code works, but there's a potential performance problem in it. +Mã này hoạt động, nhưng có một vấn đề tiềm ẩn về hiệu suất trong đó. -The method `result.includes(str)` internally walks the array `result` and compares each element against `str` to find the match. +Phương thức `result.includes(str)` đi bên trong array `result` và so sánh từng phần tử với `str` để tìm kết quả khớp. -So if there are `100` elements in `result` and no one matches `str`, then it will walk the whole `result` and do exactly `100` comparisons. And if `result` is large, like `10000`, then there would be `10000` comparisons. +Vì vậy, nếu có `100` phần tử trong `result` và không có phần tử nào khớp với `str`, thì nó sẽ duyệt toàn bộ `result` và thực hiện so sánh chính xác `100`. Và nếu `result` lớn, chẳng hạn như `10000`, thì sẽ có các phép so sánh `10000`. -That's not a problem by itself, because JavaScript engines are very fast, so walk `10000` array is a matter of microseconds. +Bản thân nó không phải là vấn đề, bởi vì các JavaScript engine rất nhanh, do đó, array `10000` walk chỉ là một phần triệu giây. -But we do such test for each element of `arr`, in the `for` loop. +Nhưng chúng ta thực hiện kiểm tra như vậy cho từng phần tử của `arr`, trong vòng lặp `for`. -So if `arr.length` is `10000` we'll have something like `10000*10000` = 100 millions of comparisons. That's a lot. +Vì vậy, nếu `arr.length` là `10000` thì chúng ta sẽ có thứ gì đó như `10000*10000` = 100 triệu phép so sánh. Đó là rất nhiều. -So the solution is only good for small arrays. +Vì vậy, giải pháp chỉ tốt cho các array nhỏ. -Further in the chapter we'll see how to optimize it. +Hơn nữa trong chương chúng ta sẽ xem cách tối ưu hóa nó. diff --git a/1-js/05-data-types/05-array-methods/11-array-unique/task.md b/1-js/05-data-types/05-array-methods/11-array-unique/task.md index 5b56d3621..7d391a5a9 100644 --- a/1-js/05-data-types/05-array-methods/11-array-unique/task.md +++ b/1-js/05-data-types/05-array-methods/11-array-unique/task.md @@ -2,13 +2,13 @@ importance: 4 --- -# Filter unique array members +# Lọc các thành viên array duy nhất -Let `arr` be an array. +Đặt `arr` là một array. -Create a function `unique(arr)` that should return an array with unique items of `arr`. +Tạo một hàm `unique(arr)` sẽ trả về một array với các phần tử duy nhất của `arr`. -For instance: +Ví dụ: ```js function unique(arr) { diff --git a/1-js/05-data-types/05-array-methods/12-reduce-object/task.md b/1-js/05-data-types/05-array-methods/12-reduce-object/task.md index d3c8f8eb1..1aa9584a3 100644 --- a/1-js/05-data-types/05-array-methods/12-reduce-object/task.md +++ b/1-js/05-data-types/05-array-methods/12-reduce-object/task.md @@ -2,13 +2,13 @@ importance: 4 --- -# Create keyed object from array +# Tạo đối tượng có khóa từ array -Let's say we received an array of users in the form `{id:..., name:..., age... }`. +Giả sử chúng ta nhận được một array người dùng ở dạng `{id:..., name:..., age... }`. -Create a function `groupById(arr)` that creates an object from it, with `id` as the key, and array items as values. +Tạo một hàm `groupById(arr)` để tạo một đối tượng từ nó, với `id` là khóa và các mục array là giá trị. -For example: +Ví dụ: ```js let users = [ @@ -20,7 +20,7 @@ let users = [ let usersById = groupById(users); /* -// after the call we should have: +// sau cuộc gọi chúng ta nên có: usersById = { john: {id: 'john', name: "John Smith", age: 20}, @@ -30,8 +30,8 @@ usersById = { */ ``` -Such function is really handy when working with server data. +Hàm như vậy thực sự tiện dụng khi làm việc với dữ liệu máy chủ. -In this task we assume that `id` is unique. There may be no two array items with the same `id`. +Trong nhiệm vụ này, chúng ta giả định rằng `id` là duy nhất. Có thể không có hai mục array nào có cùng `id`. -Please use array `.reduce` method in the solution. +Hãy sử dụng phương thức array `.reduce` trong giải pháp. diff --git a/1-js/05-data-types/05-array-methods/2-filter-range/_js.view/solution.js b/1-js/05-data-types/05-array-methods/2-filter-range/_js.view/solution.js index 0bdfbae5a..cee42492f 100644 --- a/1-js/05-data-types/05-array-methods/2-filter-range/_js.view/solution.js +++ b/1-js/05-data-types/05-array-methods/2-filter-range/_js.view/solution.js @@ -1,5 +1,5 @@ function filterRange(arr, a, b) { - // added brackets around the expression for better readability + // thêm dấu ngoặc xung quanh biểu thức để dễ đọc hơn return arr.filter(item => (a <= item && item <= b)); -} \ No newline at end of file +} diff --git a/1-js/05-data-types/05-array-methods/2-filter-range/solution.md b/1-js/05-data-types/05-array-methods/2-filter-range/solution.md index 73993a07a..3f90e2342 100644 --- a/1-js/05-data-types/05-array-methods/2-filter-range/solution.md +++ b/1-js/05-data-types/05-array-methods/2-filter-range/solution.md @@ -1,6 +1,6 @@ ```js run demo function filterRange(arr, a, b) { - // added brackets around the expression for better readability + // thêm dấu ngoặc xung quanh biểu thức để dễ đọc hơn return arr.filter(item => (a <= item && item <= b)); } @@ -8,7 +8,7 @@ let arr = [5, 3, 8, 1]; let filtered = filterRange(arr, 1, 4); -alert( filtered ); // 3,1 (matching values) +alert( filtered ); // 3,1 (giá trị trùng khớp) -alert( arr ); // 5,3,8,1 (not modified) +alert( arr ); // 5,3,8,1 (không bị sửa đổi) ``` diff --git a/1-js/05-data-types/05-array-methods/2-filter-range/task.md b/1-js/05-data-types/05-array-methods/2-filter-range/task.md index 46e47c93d..8fbbfb3cc 100644 --- a/1-js/05-data-types/05-array-methods/2-filter-range/task.md +++ b/1-js/05-data-types/05-array-methods/2-filter-range/task.md @@ -2,21 +2,20 @@ importance: 4 --- -# Filter range +# Phạm vi bộ lọc -Write a function `filterRange(arr, a, b)` that gets an array `arr`, looks for elements with values higher or equal to `a` and lower or equal to `b` and return a result as an array. +Viết một hàm `filterRange(arr, a, b)` nhận một array `arr`, tìm kiếm các phần tử có giá trị cao hơn hoặc bằng `a` và thấp hơn hoặc bằng `b` và trả về kết quả dưới dạng một array. -The function should not modify the array. It should return the new array. +Hàm không nên sửa đổi array. Nó sẽ trả về array mới. -For instance: +Ví dụ: ```js let arr = [5, 3, 8, 1]; let filtered = filterRange(arr, 1, 4); -alert( filtered ); // 3,1 (matching values) +alert( filtered ); // 3,1 (giá trị trùng khớp) -alert( arr ); // 5,3,8,1 (not modified) +alert( arr ); // 5,3,8,1 (không bị sửa đổi) ``` - diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js index 488db3755..c1cfae4b2 100644 --- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js +++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js @@ -4,11 +4,10 @@ function filterRangeInPlace(arr, a, b) { for (let i = 0; i < arr.length; i++) { let val = arr[i]; - // remove if outside of the interval + // loại bỏ nếu ở bên ngoài khoảng thời gian if (val < a || val > b) { arr.splice(i, 1); i--; } } - } diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md index 36e3130ff..81b39fa89 100644 --- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md +++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md @@ -4,7 +4,7 @@ function filterRangeInPlace(arr, a, b) { for (let i = 0; i < arr.length; i++) { let val = arr[i]; - // remove if outside of the interval + // loại bỏ nếu ở bên ngoài khoảng thời gian if (val < a || val > b) { arr.splice(i, 1); i--; @@ -15,7 +15,7 @@ function filterRangeInPlace(arr, a, b) { let arr = [5, 3, 8, 1]; -filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4 +filterRangeInPlace(arr, 1, 4); // loại bỏ các số trừ từ 1 đến 4 alert( arr ); // [3, 1] ``` diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/task.md b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/task.md index 7066a51ab..a37be46b5 100644 --- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/task.md +++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/task.md @@ -2,17 +2,17 @@ importance: 4 --- -# Filter range "in place" +# Phạm vi lọc "tại chỗ" -Write a function `filterRangeInPlace(arr, a, b)` that gets an array `arr` and removes from it all values except those that are between `a` and `b`. The test is: `a ≤ arr[i] ≤ b`. +Viết một hàm `filterRangeInPlace(arr, a, b)` nhận một array `arr` và loại bỏ khỏi array đó tất cả các giá trị ngoại trừ các giá trị nằm trong khoảng từ `a` đến `b`. Phép thử là: `a ≤ arr[i] ≤ b`. -The function should only modify the array. It should not return anything. +Hàm chỉ nên sửa đổi array. Nó không nên trả lại bất cứ điều gì. -For instance: +Ví dụ: ```js let arr = [5, 3, 8, 1]; -filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4 +filterRangeInPlace(arr, 1, 4); // loại bỏ các số trừ từ 1 đến 4 alert( arr ); // [3, 1] ``` diff --git a/1-js/05-data-types/05-array-methods/4-sort-back/task.md b/1-js/05-data-types/05-array-methods/4-sort-back/task.md index 0e3eeab76..3b3ef6c8b 100644 --- a/1-js/05-data-types/05-array-methods/4-sort-back/task.md +++ b/1-js/05-data-types/05-array-methods/4-sort-back/task.md @@ -2,12 +2,12 @@ importance: 4 --- -# Sort in decreasing order +# Sắp xếp theo thứ tự giảm dần ```js let arr = [5, 2, 1, -10, 8]; -// ... your code to sort it in decreasing order +// ... mã của bạn để sắp xếp nó theo thứ tự giảm dần alert( arr ); // 8, 5, 2, 1, -10 ``` diff --git a/1-js/05-data-types/05-array-methods/5-copy-sort-array/solution.md b/1-js/05-data-types/05-array-methods/5-copy-sort-array/solution.md index 8537b129e..57f5a059e 100644 --- a/1-js/05-data-types/05-array-methods/5-copy-sort-array/solution.md +++ b/1-js/05-data-types/05-array-methods/5-copy-sort-array/solution.md @@ -1,4 +1,4 @@ -We can use `slice()` to make a copy and run the sort on it: +Chúng ta có thể sử dụng `slice()` để tạo một bản sao và chạy sắp xếp trên đó: ```js run function copySorted(arr) { diff --git a/1-js/05-data-types/05-array-methods/5-copy-sort-array/task.md b/1-js/05-data-types/05-array-methods/5-copy-sort-array/task.md index c1395b4ad..fd09d7992 100644 --- a/1-js/05-data-types/05-array-methods/5-copy-sort-array/task.md +++ b/1-js/05-data-types/05-array-methods/5-copy-sort-array/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Copy and sort array +# Sao chép và sắp xếp array -We have an array of strings `arr`. We'd like to have a sorted copy of it, but keep `arr` unmodified. +Chúng ta có một array với các chuỗi `arr`. Chúng ta muốn có một bản sao được sắp xếp của nó, nhưng giữ nguyên `arr`. -Create a function `copySorted(arr)` that returns such a copy. +Tạo một hàm `copySorted(arr)` để trả về một bản sao như vậy. ```js let arr = ["HTML", "JavaScript", "CSS"]; @@ -14,5 +14,5 @@ let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); alert( sorted ); // CSS, HTML, JavaScript -alert( arr ); // HTML, JavaScript, CSS (no changes) +alert( arr ); // HTML, JavaScript, CSS (không thay đổi) ``` diff --git a/1-js/05-data-types/05-array-methods/6-array-get-names/task.md b/1-js/05-data-types/05-array-methods/6-array-get-names/task.md index 74c8a9d74..2c5687d15 100644 --- a/1-js/05-data-types/05-array-methods/6-array-get-names/task.md +++ b/1-js/05-data-types/05-array-methods/6-array-get-names/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Map to names +# Map đến names -You have an array of `user` objects, each one has `user.name`. Write the code that converts it into an array of names. +Bạn có một array các đối tượng `user`, mỗi đối tượng có `user.name`. Viết mã chuyển đổi nó thành một array names. -For instance: +Ví dụ: ```js no-beautify let john = { name: "John", age: 25 }; @@ -15,7 +15,7 @@ let mary = { name: "Mary", age: 28 }; let users = [ john, pete, mary ]; -let names = /* ... your code */ +let names = /* ... mã của bạn */ alert( names ); // John, Pete, Mary ``` diff --git a/1-js/05-data-types/05-array-methods/6-calculator-extendable/solution.md b/1-js/05-data-types/05-array-methods/6-calculator-extendable/solution.md index ebe0714cf..917a14251 100644 --- a/1-js/05-data-types/05-array-methods/6-calculator-extendable/solution.md +++ b/1-js/05-data-types/05-array-methods/6-calculator-extendable/solution.md @@ -1,3 +1,3 @@ -- Please note how methods are stored. They are simply added to `this.methods` property. -- All tests and numeric conversions are done in the `calculate` method. In future it may be extended to support more complex expressions. +- Hãy lưu ý cách các phương thức được lưu trữ. Chúng chỉ được thêm vào thuộc tính `this.methods`. +- Tất cả các kiểm tra và chuyển đổi số được thực hiện theo phương thức `calculate`. Trong tương lai, nó có thể được mở rộng để hỗ trợ các biểu thức phức tạp hơn. diff --git a/1-js/05-data-types/05-array-methods/6-calculator-extendable/task.md b/1-js/05-data-types/05-array-methods/6-calculator-extendable/task.md index e0d302f4c..44db4472e 100644 --- a/1-js/05-data-types/05-array-methods/6-calculator-extendable/task.md +++ b/1-js/05-data-types/05-array-methods/6-calculator-extendable/task.md @@ -2,35 +2,35 @@ importance: 5 --- -# Create an extendable calculator +# Tạo một máy tính có thể mở rộng -Create a constructor function `Calculator` that creates "extendable" calculator objects. +Tạo một constructor `Calculator` để tạo các đối tượng máy tính "có thể mở rộng". -The task consists of two parts. +Nhiệm vụ bao gồm hai phần. -1. First, implement the method `calculate(str)` that takes a string like `"1 + 2"` in the format "NUMBER operator NUMBER" (space-delimited) and returns the result. Should understand plus `+` and minus `-`. +1. Đầu tiên, triển khai phương thức `calculate(str)` nhận một chuỗi như `"1 + 2"` ở định dạng "SỐ toán tử SỐ" (phân cách bằng dấu cách) và trả về kết quả. Nên hiểu cộng `+` và trừ `-`. - Usage example: + Ví dụ sử dụng: ```js let calc = new Calculator; alert( calc.calculate("3 + 7") ); // 10 ``` -2. Then add the method `addMethod(name, func)` that teaches the calculator a new operation. It takes the operator `name` and the two-argument function `func(a,b)` that implements it. +2. Sau đó thêm phương thức `addMethod(name, func)` dạy cho máy tính một thao tác mới. Nó sử dụng toán tử `name` và hàm hai đối số `func(a,b)` để thực hiện nó. - For instance, let's add the multiplication `*`, division `/` and power `**`: + Chẳng hạn, hãy thêm phép nhân `*`, phép chia `/` và lũy thừa `**`: ```js let powerCalc = new Calculator; - powerCalc.addMethod("*", (a, b) => a * b); - powerCalc.addMethod("/", (a, b) => a / b); - powerCalc.addMethod("**", (a, b) => a ** b); + powerCalc.addMethod("nhân", (a, b) => a * b); + powerCalc.addMethod("chia", (a, b) => a / b); + powerCalc.addMethod("luỹ thừa", (a, b) => a ** b); let result = powerCalc.calculate("2 ** 3"); alert( result ); // 8 ``` -- No parentheses or complex expressions in this task. -- The numbers and the operator are delimited with exactly one space. -- There may be error handling if you'd like to add it. +- Không có dấu ngoặc đơn hay biểu thức phức tạp trong nhiệm vụ này. +- Các số và toán tử được phân cách bằng đúng một dấu cách. +- Có thể xử lý lỗi nếu bạn muốn thêm nó. diff --git a/1-js/05-data-types/05-array-methods/7-map-objects/solution.md b/1-js/05-data-types/05-array-methods/7-map-objects/solution.md index 2d8d4fb0e..1e628b68c 100644 --- a/1-js/05-data-types/05-array-methods/7-map-objects/solution.md +++ b/1-js/05-data-types/05-array-methods/7-map-objects/solution.md @@ -25,9 +25,9 @@ alert( usersMapped[0].id ); // 1 alert( usersMapped[0].fullName ); // John Smith ``` -Please note that in the arrow functions we need to use additional brackets. +Hãy lưu ý rằng trong các arrow function, chúng ta cần sử dụng các dấu ngoặc bổ sung. -We can't write like this: +Chúng ta không thể viết như thế này: ```js let usersMapped = users.map(user => *!*{*/!* fullName: `${user.name} ${user.surname}`, @@ -35,9 +35,9 @@ let usersMapped = users.map(user => *!*{*/!* }); ``` -As we remember, there are two arrow functions: without body `value => expr` and with body `value => {...}`. +Như chúng ta đã nhớ, có hai arrow function: không có phần thân `value => expr` và có phần thân `value => {...}`. -Here JavaScript would treat `{` as the start of function body, not the start of the object. The workaround is to wrap them in the "normal" brackets: +Ở đây, JavaScript sẽ coi `{` là phần bắt đầu của thân hàm, không phải phần đầu của đối tượng. Cách giải quyết là bọc chúng trong dấu ngoặc "bình thường": ```js let usersMapped = users.map(user => *!*({*/!* @@ -46,6 +46,4 @@ let usersMapped = users.map(user => *!*({*/!* })); ``` -Now fine. - - +Bây giờ thì ổn. diff --git a/1-js/05-data-types/05-array-methods/7-map-objects/task.md b/1-js/05-data-types/05-array-methods/7-map-objects/task.md index b11d12155..173a212a8 100644 --- a/1-js/05-data-types/05-array-methods/7-map-objects/task.md +++ b/1-js/05-data-types/05-array-methods/7-map-objects/task.md @@ -2,13 +2,13 @@ importance: 5 --- -# Map to objects +# Map tới các đối tượng -You have an array of `user` objects, each one has `name`, `surname` and `id`. +Bạn có một array các đối tượng `user`, mỗi đối tượng có `name`, `surname` và `id`. -Write the code to create another array from it, of objects with `id` and `fullName`, where `fullName` is generated from `name` and `surname`. +Viết mã để tạo một array khác từ nó, gồm các đối tượng có `id` và `fullName`, trong đó `fullName` được tạo từ `name` và `surname`. -For instance: +Ví dụ: ```js no-beautify let john = { name: "John", surname: "Smith", id: 1 }; @@ -18,7 +18,7 @@ let mary = { name: "Mary", surname: "Key", id: 3 }; let users = [ john, pete, mary ]; *!* -let usersMapped = /* ... your code ... */ +let usersMapped = /* ... mã của bạn ... */ */!* /* @@ -33,4 +33,4 @@ alert( usersMapped[0].id ) // 1 alert( usersMapped[0].fullName ) // John Smith ``` -So, actually you need to map one array of objects to another. Try using `=>` here. There's a small catch. \ No newline at end of file +Vì vậy, trên thực tế, bạn cần map một array đối tượng này sang array đối tượng khác. Hãy thử sử dụng `=>` tại đây. Có một nhược điểm nhỏ. diff --git a/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md b/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md index cfaf9761a..9ed78da14 100644 --- a/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md +++ b/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md @@ -11,7 +11,7 @@ let arr = [ pete, john, mary ]; sortByAge(arr); -// now sorted is: [john, mary, pete] +// bây giờ được sắp xếp là: [john, mary, pete] alert(arr[0].name); // John alert(arr[1].name); // Mary alert(arr[2].name); // Pete diff --git a/1-js/05-data-types/05-array-methods/8-sort-objects/task.md b/1-js/05-data-types/05-array-methods/8-sort-objects/task.md index 9a215c9f4..c71e2b1ca 100644 --- a/1-js/05-data-types/05-array-methods/8-sort-objects/task.md +++ b/1-js/05-data-types/05-array-methods/8-sort-objects/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Sort users by age +# Sắp xếp người dùng theo độ tuổi -Write the function `sortByAge(users)` that gets an array of objects with the `age` property and sorts them by `age`. +Viết hàm `sortByAge(users)` để lấy một array các đối tượng có thuộc tính `age` và sắp xếp chúng theo `age`. -For instance: +Ví dụ: ```js no-beautify let john = { name: "John", age: 25 }; diff --git a/1-js/05-data-types/05-array-methods/9-shuffle/solution.md b/1-js/05-data-types/05-array-methods/9-shuffle/solution.md index 6674c444f..6fa2495b8 100644 --- a/1-js/05-data-types/05-array-methods/9-shuffle/solution.md +++ b/1-js/05-data-types/05-array-methods/9-shuffle/solution.md @@ -1,4 +1,4 @@ -The simple solution could be: +Giải pháp đơn giản có thể là: ```js run *!* @@ -12,18 +12,18 @@ shuffle(arr); alert(arr); ``` -That somewhat works, because `Math.random() - 0.5` is a random number that may be positive or negative, so the sorting function reorders elements randomly. +Điều đó phần nào có tác dụng, bởi vì `Math.random() - 0.5` là một số ngẫu nhiên có thể dương hoặc âm, vì vậy hàm sắp xếp sẽ sắp xếp lại các phần tử một cách ngẫu nhiên. -But because the sorting function is not meant to be used this way, not all permutations have the same probability. +Nhưng vì hàm sắp xếp không được sử dụng theo cách này nên không phải tất cả các hoán vị đều có cùng xác suất. -For instance, consider the code below. It runs `shuffle` 1000000 times and counts appearances of all possible results: +Ví dụ, hãy xem xét đoạn mã dưới đây. Nó chạy `shuffle` 1000000 lần và đếm số lần xuất hiện của tất cả các kết quả có thể có: ```js run function shuffle(array) { array.sort(() => Math.random() - 0.5); } -// counts of appearances for all possible permutations +// số lần xuất hiện cho tất cả các hoán vị có thể let count = { '123': 0, '132': 0, @@ -39,13 +39,13 @@ for (let i = 0; i < 1000000; i++) { count[array.join('')]++; } -// show counts of all possible permutations +// hiển thị số lượng của tất cả các hoán vị có thể for (let key in count) { alert(`${key}: ${count[key]}`); } ``` -An example result (depends on JS engine): +Một kết quả ví dụ (phụ thuộc vào JS engine): ```js 123: 250706 @@ -56,30 +56,30 @@ An example result (depends on JS engine): 321: 125223 ``` -We can see the bias clearly: `123` and `213` appear much more often than others. +Chúng ta có thể thấy rõ sự thiên vị: `123` và `213` xuất hiện thường xuyên hơn nhiều so với các số khác. -The result of the code may vary between JavaScript engines, but we can already see that the approach is unreliable. +Kết quả của mã có thể khác nhau giữa các JavaScript engine, nhưng chúng ta có thể thấy rằng cách tiếp cận này không đáng tin cậy. -Why it doesn't work? Generally speaking, `sort` is a "black box": we throw an array and a comparison function into it and expect the array to be sorted. But due to the utter randomness of the comparison the black box goes mad, and how exactly it goes mad depends on the concrete implementation that differs between engines. +Tại sao nó không hoạt động? Nói chung, `sort` là một "hộp đen": chúng ta ném một array và một hàm so sánh vào đó và mong muốn array được sắp xếp. Nhưng do sự so sánh hoàn toàn ngẫu nhiên, hộp đen trở nên điên loạn và chính xác thì nó điên rồ như thế nào phụ thuộc vào việc triển khai cụ thể khác nhau giữa các engine. -There are other good ways to do the task. For instance, there's a great algorithm called [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). The idea is to walk the array in the reverse order and swap each element with a random one before it: +Có nhiều cách tốt khác để thực hiện nhiệm vụ. Chẳng hạn, có một thuật toán tuyệt vời gọi là [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). Ý tưởng là di chuyển array theo thứ tự ngược lại và hoán đổi từng phần tử với một phần tử ngẫu nhiên trước nó: ```js function shuffle(array) { for (let i = array.length - 1; i > 0; i--) { - let j = Math.floor(Math.random() * (i + 1)); // random index from 0 to i + let j = Math.floor(Math.random() * (i + 1)); // chỉ mục ngẫu nhiên từ 0 đến i - // swap elements array[i] and array[j] - // we use "destructuring assignment" syntax to achieve that - // you'll find more details about that syntax in later chapters - // same can be written as: + // hoán đổi phần tử array[i] và array[j] + // chúng ta sử dụng cú pháp "phân công phá hủy" để đạt được điều đó + // bạn sẽ tìm thấy thêm chi tiết về cú pháp đó trong các chương sau + // tương tự có thể được viết là: // let t = array[i]; array[i] = array[j]; array[j] = t [array[i], array[j]] = [array[j], array[i]]; } } ``` -Let's test it the same way: +Hãy kiểm tra nó theo cùng một cách: ```js run function shuffle(array) { @@ -89,7 +89,7 @@ function shuffle(array) { } } -// counts of appearances for all possible permutations +// số lần xuất hiện cho tất cả các hoán vị có thể let count = { '123': 0, '132': 0, @@ -105,13 +105,13 @@ for (let i = 0; i < 1000000; i++) { count[array.join('')]++; } -// show counts of all possible permutations +// hiển thị số lượng của tất cả các hoán vị có thể for (let key in count) { alert(`${key}: ${count[key]}`); } ``` -The example output: +Đầu ra ví dụ: ```js 123: 166693 @@ -122,6 +122,6 @@ The example output: 321: 166316 ``` -Looks good now: all permutations appear with the same probability. +Bây giờ có vẻ tốt: tất cả các hoán vị xuất hiện với cùng xác suất. -Also, performance-wise the Fisher-Yates algorithm is much better, there's no "sorting" overhead. +Ngoài ra, về hiệu suất, thuật toán Fisher-Yates tốt hơn nhiều, không có chi phí "sắp xếp". diff --git a/1-js/05-data-types/05-array-methods/9-shuffle/task.md b/1-js/05-data-types/05-array-methods/9-shuffle/task.md index 970c53417..3847c4152 100644 --- a/1-js/05-data-types/05-array-methods/9-shuffle/task.md +++ b/1-js/05-data-types/05-array-methods/9-shuffle/task.md @@ -2,11 +2,11 @@ importance: 3 --- -# Shuffle an array +# Xáo trộn một array -Write the function `shuffle(array)` that shuffles (randomly reorders) elements of the array. +Viết hàm `shuffle(array)` để xáo trộn (sắp xếp lại ngẫu nhiên) các phần tử của array. -Multiple runs of `shuffle` may lead to different orders of elements. For instance: +Nhiều lần chạy `shuffle` có thể dẫn đến các thứ tự phần tử khác nhau. Ví dụ: ```js let arr = [1, 2, 3]; @@ -22,4 +22,4 @@ shuffle(arr); // ... ``` -All element orders should have an equal probability. For instance, `[1,2,3]` can be reordered as `[1,2,3]` or `[1,3,2]` or `[3,1,2]` etc, with equal probability of each case. +Tất cả các thứ tự phần tử phải có xác suất bằng nhau. Chẳng hạn, `[1,2,3]` có thể được sắp xếp lại thành `[1,2,3]` hoặc `[1,3,2]` hoặc `[3,1,2]`, v.v. với xác suất bằng nhau của từng trường hợp. diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md index b14e9a0be..213f6d3e0 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -1,111 +1,111 @@ -# Array methods +# Phương thức array -Arrays provide a lot of methods. To make things easier, in this chapter they are split into groups. +Array cung cấp rất nhiều phương thức. Để làm cho mọi thứ dễ dàng hơn, trong chương này chúng được chia thành các nhóm. -## Add/remove items +## Thêm/xóa item -We already know methods that add and remove items from the beginning or the end: +Chúng ta đã biết các phương thức thêm và xóa các item từ đầu hoặc cuối: -- `arr.push(...items)` -- adds items to the end, -- `arr.pop()` -- extracts an item from the end, -- `arr.shift()` -- extracts an item from the beginning, -- `arr.unshift(...items)` -- adds items to the beginning. +- `arr.push(...items)` -- thêm các item vào cuối, +- `arr.pop()` -- trích xuất một item từ cuối, +- `arr.shift()` -- trích xuất một item từ đầu, +- `arr.unshift(...items)` -- thêm các item vào đầu. -Here are a few others. +Dưới đây là một số khác. ### splice -How to delete an element from the array? +Làm cách nào để xóa một phần tử khỏi array? -The arrays are objects, so we can try to use `delete`: +Các array là các đối tượng, vì vậy chúng ta có thể thử sử dụng `delete`: ```js run -let arr = ["I", "go", "home"]; +let arr = ["Tôi", "về", "nhà"]; -delete arr[1]; // remove "go" +delete arr[1]; // loại bỏ "về" alert( arr[1] ); // undefined -// now arr = ["I", , "home"]; +// bây giờ arr = ["Tôi",,"nhà"]; alert( arr.length ); // 3 ``` -The element was removed, but the array still has 3 elements, we can see that `arr.length == 3`. +Phần tử đã bị xóa, nhưng array vẫn còn 3 phần tử, chúng ta có thể thấy rằng `arr.length == 3`. -That's natural, because `delete obj.key` removes a value by the `key`. It's all it does. Fine for objects. But for arrays we usually want the rest of elements to shift and occupy the freed place. We expect to have a shorter array now. +Điều đó là bình thường, bởi vì `delete obj.key` sẽ xóa một giá trị bằng `key`. Đó là tất cả những gì nó làm. Phạt đối với các đối tượng. Nhưng đối với array, chúng ta thường muốn các phần tử còn lại dịch chuyển và chiếm vị trí được giải phóng. Chúng ta hy vọng sẽ có một array ngắn hơn bây giờ. -So, special methods should be used. +Vì vậy, các phương thức đặc biệt nên được sử dụng. -The [arr.splice](mdn:js/Array/splice) method is a swiss army knife for arrays. It can do everything: insert, remove and replace elements. +Phương thức [arr.splice](mdn:js/Array/splice) là một con dao quân đội Thụy Sĩ dành cho array. Nó có thể làm mọi thứ: chèn, xóa và thay thế các phần tử. -The syntax is: +Cú pháp là: ```js arr.splice(start[, deleteCount, elem1, ..., elemN]) ``` -It modifies `arr` starting from the index `start`: removes `deleteCount` elements and then inserts `elem1, ..., elemN` at their place. Returns the array of removed elements. +Nó sửa đổi `arr` bắt đầu từ chỉ mục `start`: loại bỏ các phần tử `deleteCount` và sau đó chèn `elem1, ..., elemN` vào vị trí của chúng. Trả về array các phần tử đã loại bỏ. -This method is easy to grasp by examples. +Phương pháp này rất dễ nắm bắt bằng các ví dụ. -Let's start with the deletion: +Hãy bắt đầu với việc xóa: ```js run -let arr = ["I", "study", "JavaScript"]; +let arr = ["Tôi", "học", "JavaScript"]; *!* -arr.splice(1, 1); // from index 1 remove 1 element +arr.splice(1, 1); // từ chỉ mục 1 loại bỏ 1 phần tử */!* -alert( arr ); // ["I", "JavaScript"] +alert( arr ); // ["Tôi","JavaScript"] ``` -Easy, right? Starting from the index `1` it removed `1` element. +Dễ, phải không? Bắt đầu từ chỉ mục `1` nó đã loại bỏ phần tử `1`. -In the next example we remove 3 elements and replace them with the other two: +Trong ví dụ tiếp theo, chúng ta loại bỏ 3 phần tử và thay thế chúng bằng hai phần tử còn lại: ```js run -let arr = [*!*"I", "study", "JavaScript",*/!* "right", "now"]; +let arr = [*!*"Tôi", "đang học", "JavaScript",*/!* "ngay", "bây giờ"]; -// remove 3 first elements and replace them with another -arr.splice(0, 3, "Let's", "dance"); +// xóa 3 phần tử đầu tiên và thay thế chúng bằng phần tử khác +arr.splice(0, 3, "Hãy", "nhảy"); -alert( arr ) // now [*!*"Let's", "dance"*/!*, "right", "now"] +alert( arr ) // now [*!*"Hãy", "nhảy"*/!*, "ngay", "bây giờ"] ``` -Here we can see that `splice` returns the array of removed elements: +Ở đây chúng ta có thể thấy rằng `splice` trả về array các phần tử đã loại bỏ: ```js run -let arr = [*!*"I", "study",*/!* "JavaScript", "right", "now"]; +let arr = [*!*"Tôi", "đang học",*/!* "JavaScript", "ngay", "bây giờ"]; -// remove 2 first elements +// loại bỏ 2 phần tử đầu tiên let removed = arr.splice(0, 2); -alert( removed ); // "I", "study" <-- array of removed elements +alert( removed ); // "Tôi","học" <-- array của các phần tử bị loại bỏ ``` -The `splice` method is also able to insert the elements without any removals. For that we need to set `deleteCount` to `0`: +Phương thức `splice` cũng có thể chèn các phần tử mà không cần xóa. Để làm được điều đó, chúng ta cần đặt `deleteCount` thành `0`: ```js run -let arr = ["I", "study", "JavaScript"]; +let arr = ["Tôi", "học", "JavaScript"]; -// from index 2 -// delete 0 -// then insert "complex" and "language" -arr.splice(2, 0, "complex", "language"); +// từ chỉ mục 2 +// xóa 0 +// sau đó chèn "ngôn ngữ" và "phức tạp" +arr.splice(2, 0, "ngôn ngữ", "phức tạp"); -alert( arr ); // "I", "study", "complex", "language", "JavaScript" +alert( arr ); // Tôi,học,ngôn ngữ,phức tạp,JavaScript ``` -````smart header="Negative indexes allowed" -Here and in other array methods, negative indexes are allowed. They specify the position from the end of the array, like here: +````smart header="Cho phép chỉ mục âm" +Ở đây và trong các phương thức array khác, chỉ mục âm được cho phép. Chúng chỉ định vị trí từ cuối array, như ở đây: ```js run let arr = [1, 2, 5]; -// from index -1 (one step from the end) -// delete 0 elements, -// then insert 3 and 4 +// từ chỉ mục -1 (một bước từ cuối) +// xóa 0 phần tử, +// sau đó chèn 3 và 4 arr.splice(-1, 0, 3, 4); alert( arr ); // 1,2,3,4,5 @@ -114,133 +114,133 @@ alert( arr ); // 1,2,3,4,5 ### slice -The method [arr.slice](mdn:js/Array/slice) is much simpler than similar-looking `arr.splice`. +Phương thức [arr.slice](mdn:js/Array/slice) đơn giản hơn nhiều so với `arr.splice` có giao diện tương tự. -The syntax is: +Cú pháp là: ```js arr.slice([start], [end]) ``` -It returns a new array copying to it all items from index `start` to `end` (not including `end`). Both `start` and `end` can be negative, in that case position from array end is assumed. +Nó trả về một array mới và sao chép vào nó tất cả các mục từ chỉ mục `start` đến `end` (không bao gồm `end`). Cả `start` và `end` đều có thể âm, trong trường hợp đó, vị trí từ cuối array được giả định. -It's similar to a string method `str.slice`, but instead of substrings it makes subarrays. +Nó tương tự như một phương thức chuỗi `str.slice`, nhưng thay vì các chuỗi con, nó tạo ra các array con. -For instance: +Ví dụ: ```js run let arr = ["t", "e", "s", "t"]; -alert( arr.slice(1, 3) ); // e,s (copy from 1 to 3) +alert( arr.slice(1, 3) ); // e,s (sao chép từ 1 đến 3) -alert( arr.slice(-2) ); // s,t (copy from -2 till the end) +alert( arr.slice(-2) ); // s,t (sao chép từ -2 đến hết) ``` -We can also call it without arguments: `arr.slice()` creates a copy of `arr`. That's often used to obtain a copy for further transformations that should not affect the original array. +Chúng ta cũng có thể gọi nó mà không cần đối số: `arr.slice()` tạo một bản sao của `arr`. Điều đó thường được sử dụng để lấy một bản sao cho các phép biến đổi tiếp theo không ảnh hưởng đến array ban đầu. ### concat -The method [arr.concat](mdn:js/Array/concat) creates a new array that includes values from other arrays and additional items. +Phương thức [arr.concat](mdn:js/Array/concat) tạo một array mới bao gồm các giá trị từ các array khác và các mục bổ sung. -The syntax is: +Cú pháp là: ```js arr.concat(arg1, arg2...) ``` -It accepts any number of arguments -- either arrays or values. +Nó chấp nhận bất kỳ số lượng đối số nào -- aray hoặc giá trị. -The result is a new array containing items from `arr`, then `arg1`, `arg2` etc. +Kết quả là một array mới chứa các mục từ `arr`, sau đó là `arg1`, `arg2`, v.v. -If an argument `argN` is an array, then all its elements are copied. Otherwise, the argument itself is copied. +Nếu một đối số `argN` là một array, thì tất cả các phần tử của nó sẽ được sao chép. Nếu không, chính đối số sẽ được sao chép. -For instance: +Ví dụ: ```js run let arr = [1, 2]; -// create an array from: arr and [3,4] +// tạo một array từ: arr và [3,4] alert( arr.concat([3, 4]) ); // 1,2,3,4 -// create an array from: arr and [3,4] and [5,6] +// tạo một array từ: arr và [3,4] và [5,6] alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 -// create an array from: arr and [3,4], then add values 5 and 6 +// tạo một array từ: arr và [3,4], sau đó thêm các giá trị 5 và 6 alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6 ``` -Normally, it only copies elements from arrays. Other objects, even if they look like arrays, are added as a whole: +Thông thường, nó chỉ sao chép các phần tử từ array. Các đối tượng khác, ngay cả khi chúng có dạng array, được thêm vào như một tổng thể: ```js run let arr = [1, 2]; let arrayLike = { - 0: "something", + 0: "thứ gì", length: 1 }; alert( arr.concat(arrayLike) ); // 1,2,[object Object] ``` -...But if an array-like object has a special `Symbol.isConcatSpreadable` property, then it's treated as an array by `concat`: its elements are added instead: +...Nhưng nếu một đối tượng dạng array có thuộc tính `Symbol.isConcatSpreadable` đặc biệt, thì nó được `concat` coi là một array: thay vào đó, các phần tử của nó được thêm vào: ```js run let arr = [1, 2]; let arrayLike = { - 0: "something", - 1: "else", + 0: "thứ gì", + 1: "đó", *!* [Symbol.isConcatSpreadable]: true, */!* length: 2 }; -alert( arr.concat(arrayLike) ); // 1,2,something,else +alert( arr.concat(arrayLike) ); // 1,2,thứ gì,đó ``` -## Iterate: forEach +## Lặp đi lặp lại: forEach -The [arr.forEach](mdn:js/Array/forEach) method allows to run a function for every element of the array. +Phương thức [arr.forEach](mdn:js/Array/forEach) cho phép chạy một hàm cho mọi phần tử của array. -The syntax: +Cú pháp: ```js arr.forEach(function(item, index, array) { - // ... do something with item + // ... làm một cái gì đó với item }); ``` -For instance, this shows each element of the array: +Chẳng hạn, thứ này cho thấy từng phần tử của aray: ```js run -// for each element call alert +// cho mỗi cuộc gọi alert phần tử ["Bilbo", "Gandalf", "Nazgul"].forEach(alert); ``` -And this code is more elaborate about their positions in the target array: +Và đoạn mã này chi tiết hơn về vị trí của chúng trong array mục tiêu: ```js run ["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => { - alert(`${item} is at index ${index} in ${array}`); + alert(`${item} đang ở chỉ mục ${index} trong ${array}`); }); ``` -The result of the function (if it returns any) is thrown away and ignored. +Kết quả của hàm (nếu nó trả về bất kỳ) bị loại bỏ và bỏ qua. -## Searching in array +## Tìm kiếm trong array -Now let's cover methods that search in an array. +Bây giờ hãy xem các phương thức tìm kiếm trong một array. -### indexOf/lastIndexOf and includes +### indexOf/lastIndexOf và includes -The methods [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) and [arr.includes](mdn:js/Array/includes) have the same syntax and do essentially the same as their string counterparts, but operate on items instead of characters: +Các phương thức [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) và [arr.includes](mdn:js/Array/includes) có cùng cú pháp và về cơ bản giống như các đối tác chuỗi của chúng, nhưng hoạt động trên các item thay vì các ký tự: -- `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`. -- `arr.lastIndexOf(item, from)` -- same, but looks for from right to left. -- `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found. +- `arr.indexOf(item, from)` -- tìm kiếm `item` bắt đầu từ chỉ mục `from` và trả về chỉ mục nơi nó được tìm thấy, nếu không thì `-1`. +- `arr.lastIndexOf(item, from)` -- tương tự, nhưng tìm kiếm từ phải sang trái. +- `arr.includes(item, from)` -- tìm kiếm `item` bắt đầu từ chỉ mục `from`, trả về `true` nếu tìm thấy. -For instance: +Ví dụ: ```js run let arr = [1, 0, false]; @@ -252,41 +252,41 @@ alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // true ``` -Note that the methods use `===` comparison. So, if we look for `false`, it finds exactly `false` and not the zero. +Lưu ý rằng các phương thức sử dụng phép so sánh `===`. Vì vậy, nếu chúng ta tìm kiếm `false`, nó sẽ tìm thấy chính xác `false` chứ không phải số 0. -If we want to check for inclusion, and don't want to know the exact index, then `arr.includes` is preferred. +Nếu chúng ta muốn kiểm tra bao hàm và không muốn biết chỉ mục chính xác, thì `arr.includes` sẽ được ưu tiên hơn. -Also, a very minor difference of `includes` is that it correctly handles `NaN`, unlike `indexOf/lastIndexOf`: +Ngoài ra, một điểm khác biệt rất nhỏ của `includes` là nó xử lý chính xác `NaN`, không giống như `indexOf/lastIndexOf`: ```js run const arr = [NaN]; -alert( arr.indexOf(NaN) ); // -1 (should be 0, but === equality doesn't work for NaN) -alert( arr.includes(NaN) );// true (correct) +alert( arr.indexOf(NaN) ); // -1 (phải là 0, nhưng đẳng thức === không hoạt động đối với NaN) +alert( arr.includes(NaN) );// true (chính xác) ``` ### find and findIndex -Imagine we have an array of objects. How do we find an object with the specific condition? +Hãy tưởng tượng chúng ta có một array các đối tượng. Làm thế nào để chúng ta tìm thấy một đối tượng với điều kiện cụ thể? -Here the [arr.find(fn)](mdn:js/Array/find) method comes in handy. +Ở đây, phương thức [arr.find(fn)](mdn:js/Array/find) rất hữu ích. -The syntax is: +Cú pháp là: ```js let result = arr.find(function(item, index, array) { - // if true is returned, item is returned and iteration is stopped - // for falsy scenario returns undefined + // nếu true được trả về, item được trả lại và quá trình lặp lại bị dừng + // đối với tập lệnh sai trả về undefined }); ``` -The function is called for elements of the array, one after another: +Hàm được gọi lần lượt cho các phần tử của array: -- `item` is the element. -- `index` is its index. -- `array` is the array itself. +- `item` là phần tử. +- `index` là chỉ mục của nó. +- `array` là chính array đó. -If it returns `true`, the search is stopped, the `item` is returned. If nothing found, `undefined` is returned. +Nếu nó trả về `true`, quá trình tìm kiếm được dừng, `item` được trả về. Nếu không tìm thấy gì, `undefined` được trả về. -For example, we have an array of users, each with the fields `id` and `name`. Let's find the one with `id == 1`: +Ví dụ: chúng ta có một array user, mỗi người có các `id` và `name`. Hãy tìm cái có `id == 1`: ```js run let users = [ @@ -300,28 +300,28 @@ let user = users.find(item => item.id == 1); alert(user.name); // John ``` -In real life arrays of objects is a common thing, so the `find` method is very useful. +Trong thực tế, các array đối tượng là một điều phổ biến, vì vậy phương thức `find` rất hữu ích. -Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. That's typical, other arguments of this function are rarely used. +Lưu ý rằng trong ví dụ này, chúng ta cung cấp cho `tìm` hàm `item => item.id == 1` với một đối số. Đó là điển hình, các đối số khác của hàm này hiếm khi được sử dụng. -The [arr.findIndex](mdn:js/Array/findIndex) method is essentially the same, but it returns the index where the element was found instead of the element itself and `-1` is returned when nothing is found. +Phương thức [arr.findIndex](mdn:js/Array/findIndex) về cơ bản giống nhau, nhưng nó trả về chỉ mục nơi phần tử được tìm thấy thay vì chính phần tử đó và `-1` được trả về khi không tìm thấy gì. ### filter -The `find` method looks for a single (first) element that makes the function return `true`. +Phương thức `find` tìm kiếm một phần tử duy nhất (đầu tiên) làm cho hàm trả về `true`. -If there may be many, we can use [arr.filter(fn)](mdn:js/Array/filter). +Nếu có nhiều, chúng ta có thể sử dụng [arr.filter(fn)](mdn:js/Array/filter). -The syntax is similar to `find`, but `filter` returns an array of all matching elements: +Cú pháp tương tự như `find`, nhưng `filter` trả về một array gồm tất cả các phần tử phù hợp: ```js let results = arr.filter(function(item, index, array) { - // if true item is pushed to results and the iteration continues - // returns empty array if nothing found + // nếu true, item được đẩy đến kết quả và quá trình lặp lại tiếp tục + // trả về array rỗng nếu không tìm thấy gì }); ``` -For instance: +Ví dụ: ```js run let users = [ @@ -330,31 +330,31 @@ let users = [ {id: 3, name: "Mary"} ]; -// returns array of the first two users +// trả về array của hai người dùng đầu tiên let someUsers = users.filter(item => item.id < 3); alert(someUsers.length); // 2 ``` -## Transform an array +## Biến đổi một array -Let's move on to methods that transform and reorder an array. +Hãy chuyển sang các phương thức biến đổi và sắp xếp lại một array. ### map -The [arr.map](mdn:js/Array/map) method is one of the most useful and often used. +Phương thức [arr.map](mdn:js/Array/map) là một trong những phương thức hữu ích nhất và thường được sử dụng. -It calls the function for each element of the array and returns the array of results. +Nó gọi hàm cho từng phần tử của array và trả về array kết quả. -The syntax is: +Cú pháp là: ```js let result = arr.map(function(item, index, array) { - // returns the new value instead of item + // trả về giá trị mới thay vì item }); ``` -For instance, here we transform each element into its length: +Chẳng hạn, ở đây chúng ta chuyển đổi từng phần tử thành độ dài của nó: ```js run let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length); @@ -363,41 +363,41 @@ alert(lengths); // 5,7,6 ### sort(fn) -The call to [arr.sort()](mdn:js/Array/sort) sorts the array *in place*, changing its element order. +Lệnh gọi [arr.sort()](mdn:js/Array/sort) sắp xếp array *tại chỗ*, thay đổi thứ tự phần tử của nó. -It also returns the sorted array, but the returned value is usually ignored, as `arr` itself is modified. +Nó cũng trả về array đã sắp xếp, nhưng giá trị được trả về thường bị bỏ qua vì bản thân `arr` đã được sửa đổi. -For instance: +Ví dụ: ```js run let arr = [ 1, 2, 15 ]; -// the method reorders the content of arr +// phương thức sắp xếp lại nội dung của arr arr.sort(); alert( arr ); // *!*1, 15, 2*/!* ``` -Did you notice anything strange in the outcome? +Bạn có nhận thấy bất cứ điều gì lạ trong kết quả không? -The order became `1, 15, 2`. Incorrect. But why? +Thứ tự trở thành `1, 15, 2`. Nó không đúng. Nhưng tại sao? -**The items are sorted as strings by default.** +**Các mục được sắp xếp theo chuỗi theo mặc định.** -Literally, all elements are converted to strings for comparisons. For strings, lexicographic ordering is applied and indeed `"2" > "15"`. +Theo nghĩa đen, tất cả các phần tử được chuyển đổi thành chuỗi để so sánh. Đối với chuỗi, thứ tự từ điển được áp dụng và thực sự là `"2" > "15"`. -To use our own sorting order, we need to supply a function as the argument of `arr.sort()`. +Để sử dụng thứ tự sắp xếp của riêng mình, chúng ta cần cung cấp một hàm làm đối số của `arr.sort()`. -The function should compare two arbitrary values and return: +Hàm sẽ so sánh hai giá trị tùy ý và trả về: ```js function compare(a, b) { - if (a > b) return 1; // if the first value is greater than the second - if (a == b) return 0; // if values are equal - if (a < b) return -1; // if the first value is less than the second + if (a > b) return 1; // nếu giá trị đầu tiên lớn hơn giá trị thứ hai + if (a == b) return 0; // nếu các giá trị bằng nhau + if (a < b) return -1; // nếu giá trị đầu tiên nhỏ hơn giá trị thứ hai } ``` -For instance, to sort as numbers: +Chẳng hạn, để sắp xếp dưới dạng số: ```js run function compareNumeric(a, b) { @@ -415,13 +415,13 @@ arr.sort(compareNumeric); alert(arr); // *!*1, 2, 15*/!* ``` -Now it works as intended. +Bây giờ nó hoạt động như dự tính. -Let's step aside and think what's happening. The `arr` can be array of anything, right? It may contain numbers or strings or objects or whatever. We have a set of *some items*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order. +Hãy bước sang một bên và suy nghĩ những gì đang xảy ra. `array` có thể là array của bất kỳ thứ gì, phải không? Nó có thể chứa số hoặc chuỗi hoặc đối tượng hoặc bất cứ thứ gì. Chúng ta có một tập hợp *một số item*. Để sắp xếp nó, chúng ta cần một *hàm sắp xếp thứ tự* biết cách so sánh các phần tử của nó. Mặc định là thứ tự chuỗi. -The `arr.sort(fn)` method implements a generic sorting algorithm. We don't need to care how it internally works (an optimized [quicksort](https://en.wikipedia.org/wiki/Quicksort) or [Timsort](https://en.wikipedia.org/wiki/Timsort) most of the time). It will walk the array, compare its elements using the provided function and reorder them, all we need is to provide the `fn` which does the comparison. +Phương thức `arr.sort(fn)` triển khai thuật toán sắp xếp chung. Chúng ta không cần quan tâm nó hoạt động bên trong như thế nào ([quicksort](https://vi.wikipedia.org/wiki/Sắp_xếp_nhanh) được tối ưu hóa) hay [Timsort](https://en.wikipedia.org/wiki/Timsort) ) hầu hết thời gian). Nó sẽ duyệt array, so sánh các phần tử của nó bằng cách sử dụng hàm được cung cấp và sắp xếp lại chúng, tất cả những gì chúng ta cần là cung cấp `fn` để so sánh. -By the way, if we ever want to know which elements are compared -- nothing prevents from alerting them: +Nhân tiện, nếu chúng ta muốn biết phần tử nào được so sánh -- không có gì ngăn cản việc alert chúng: ```js run [1, -2, 15, 2, 0, 8].sort(function(a, b) { @@ -430,12 +430,12 @@ By the way, if we ever want to know which elements are compared -- nothing preve }); ``` -The algorithm may compare an element with multiple others in the process, but it tries to make as few comparisons as possible. +Thuật toán có thể so sánh một phần tử với nhiều phần tử khác trong quy trình, nhưng nó cố gắng thực hiện càng ít phép so sánh càng tốt. -````smart header="A comparison function may return any number" -Actually, a comparison function is only required to return a positive number to say "greater" and a negative number to say "less". +````smart header="Hàm so sánh có thể trả về bất kỳ số nào" +Trên thực tế, một hàm so sánh chỉ được yêu cầu trả về một số dương để nói "lớn hơn" và một số âm để nói "ít hơn". -That allows to write shorter functions: +Điều đó cho phép viết các hàm ngắn hơn: ```js run let arr = [ 1, 2, 15 ]; @@ -446,37 +446,37 @@ alert(arr); // *!*1, 2, 15*/!* ``` ```` -````smart header="Arrow functions for the best" -Remember [arrow functions](info:arrow-functions-basics)? We can use them here for neater sorting: +````smart header="Arrow function để tốt nhất" +Bạn có nhớ [arrow function](info:arrow-functions-basics) không? Chúng ta có thể sử dụng chúng ở đây để sắp xếp gọn gàng hơn: ```js arr.sort( (a, b) => a - b ); ``` -This works exactly the same as the longer version above. +Cái này hoạt động chính xác giống như phiên bản dài hơn ở trên. ```` -````smart header="Use `localeCompare` for strings" -Remember [strings](info:string#correct-comparisons) comparison algorithm? It compares letters by their codes by default. +````smart header="Sử dụng `localeCompare` cho các chuỗi" +Nhớ thuật toán so sánh [các chuỗi](info:string#true-comparisons) không? Nó so sánh các chữ cái theo mã của chúng theo mặc định. -For many alphabets, it's better to use `str.localeCompare` method to correctly sort letters, such as `Ö`. +Đối với nhiều bảng chữ cái, tốt hơn nên sử dụng phương pháp `str.localeCompare` để sắp xếp chính xác các chữ cái, chẳng hạn như `Ö`. -For example, let's sort a few countries in German: +Ví dụ: hãy sắp xếp một vài quốc gia bằng tiếng Đức: ```js run let countries = ['Österreich', 'Andorra', 'Vietnam']; -alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (wrong) +alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (sai) -alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (correct!) +alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (chính xác!) ``` ```` ### reverse -The method [arr.reverse](mdn:js/Array/reverse) reverses the order of elements in `arr`. +Phương thức [arr.reverse](mdn:js/Array/reverse) đảo ngược thứ tự các phần tử trong `arr`. -For instance: +Ví dụ: ```js run let arr = [1, 2, 3, 4, 5]; @@ -485,15 +485,15 @@ arr.reverse(); alert( arr ); // 5,4,3,2,1 ``` -It also returns the array `arr` after the reversal. +Nó cũng trả về array `arr` sau khi đảo ngược. ### split and join -Here's the situation from real life. We are writing a messaging app, and the person enters the comma-delimited list of receivers: `John, Pete, Mary`. But for us an array of names would be much more comfortable than a single string. How to get it? +Đây là tình huống từ cuộc sống thực. Chúng ta đang viết một ứng dụng nhắn tin và người đó nhập danh sách người nhận được phân tách bằng dấu phẩy: `John, Pete, Mary`. Nhưng đối với chúng ta, một dãy tên sẽ thoải mái hơn nhiều so với một chuỗi. Làm thế nào để có được nó? -The [str.split(delim)](mdn:js/String/split) method does exactly that. It splits the string into an array by the given delimiter `delim`. +Phương thức [str.split(delim)](mdn:js/String/split) thực hiện chính xác điều đó. Nó chia chuỗi thành một array bằng dấu phân cách đã cho `delim`. -In the example below, we split by a comma followed by space: +Trong ví dụ bên dưới, chúng ta chia tách bằng dấu phẩy theo sau là dấu cách: ```js run let names = 'Bilbo, Gandalf, Nazgul'; @@ -501,11 +501,11 @@ let names = 'Bilbo, Gandalf, Nazgul'; let arr = names.split(', '); for (let name of arr) { - alert( `A message to ${name}.` ); // A message to Bilbo (and other names) + alert( `Một tin nhắn đến ${name}.` ); // Một tin nhắn tới Bilbo (và những cái tên khác) } ``` -The `split` method has an optional second numeric argument -- a limit on the array length. If it is provided, then the extra elements are ignored. In practice it is rarely used though: +Phương thức `split` có đối số số thứ hai tùy chọn -- giới hạn về độ dài array. Nếu nó được cung cấp, thì các phần tử bổ sung sẽ bị bỏ qua. Tuy nhiên trong thực tế, nó hiếm khi được sử dụng: ```js run let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); @@ -513,8 +513,8 @@ let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); alert(arr); // Bilbo, Gandalf ``` -````smart header="Split into letters" -The call to `split(s)` with an empty `s` would split the string into an array of letters: +````smart header="Chia thành các chữ cái" +Lệnh gọi `split(s)` với một `s` trống sẽ chia chuỗi thành một mảng các chữ cái: ```js run let str = "test"; @@ -523,27 +523,27 @@ alert( str.split('') ); // t,e,s,t ``` ```` -The call [arr.join(glue)](mdn:js/Array/join) does the reverse to `split`. It creates a string of `arr` items joined by `glue` between them. +Lệnh gọi [arr.join(glue)](mdn:js/Array/join) thực hiện ngược lại với `split`. Nó tạo ra một chuỗi các mục `arr` được nối bằng `glue` giữa chúng. -For instance: +Ví dụ: ```js run let arr = ['Bilbo', 'Gandalf', 'Nazgul']; -let str = arr.join(';'); // glue the array into a string using ; +let str = arr.join(';'); // dán array vào một chuỗi bằng cách sử dụng ; alert( str ); // Bilbo;Gandalf;Nazgul ``` ### reduce/reduceRight -When we need to iterate over an array -- we can use `forEach`, `for` or `for..of`. +Khi chúng ta cần lặp lại một array -- chúng ta có thể sử dụng `forEach`, `for` hoặc `for..of`. -When we need to iterate and return the data for each element -- we can use `map`. +Khi chúng ta cần lặp lại và trả về dữ liệu cho từng phần tử -- chúng ta có thể sử dụng `map`. -The methods [arr.reduce](mdn:js/Array/reduce) and [arr.reduceRight](mdn:js/Array/reduceRight) also belong to that breed, but are a little bit more intricate. They are used to calculate a single value based on the array. +Các phương thức [arr.reduce](mdn:js/Array/reduce) và [arr.reduceRight](mdn:js/Array/reduceRight) cũng thuộc loại đó, nhưng phức tạp hơn một chút. Chúng được sử dụng để tính toán một giá trị duy nhất dựa trên array. -The syntax is: +Cú pháp là: ```js let value = arr.reduce(function(accumulator, item, index, array) { @@ -551,24 +551,24 @@ let value = arr.reduce(function(accumulator, item, index, array) { }, [initial]); ``` -The function is applied to all array elements one after another and "carries on" its result to the next call. +Hàm này lần lượt được áp dụng cho tất cả các phần tử array và "tiếp tục" kết quả của nó cho lần gọi tiếp theo. -Arguments: +Các đối số: -- `accumulator` -- is the result of the previous function call, equals `initial` the first time (if `initial` is provided). -- `item` -- is the current array item. -- `index` -- is its position. -- `array` -- is the array. +- `accumulator` -- là kết quả của lệnh gọi hàm trước đó, bằng `initial` trong lần đầu tiên (nếu `initial` được cung cấp). +- `item` -- là mục array hiện tại. +- `index` -- là vị trí của nó. +- `array` -- là array. -As function is applied, the result of the previous function call is passed to the next one as the first argument. +Khi hàm được áp dụng, kết quả của lệnh gọi hàm trước được chuyển sang hàm tiếp theo dưới dạng đối số đầu tiên. -So, the first argument is essentially the accumulator that stores the combined result of all previous executions. And at the end it becomes the result of `reduce`. +Vì vậy, đối số đầu tiên về cơ bản là bộ tích lũy lưu trữ kết quả tổng hợp của tất cả các lần thực hiện trước đó. Và cuối cùng, nó trở thành kết quả của `reduce`. -Sounds complicated? +Có vẻ phức tạp? -The easiest way to grasp that is by example. +Cách dễ nhất để nắm bắt điều đó là bằng ví dụ. -Here we get a sum of an array in one line: +Ở đây chúng ta nhận được tổng của một array trong một dòng: ```js run let arr = [1, 2, 3, 4, 5]; @@ -578,74 +578,74 @@ let result = arr.reduce((sum, current) => sum + current, 0); alert(result); // 15 ``` -The function passed to `reduce` uses only 2 arguments, that's typically enough. +Hàm được truyền cho `reduce` chỉ sử dụng 2 đối số, như vậy thường là đủ. -Let's see the details of what's going on. +Hãy xem chi tiết những gì đang xảy ra. -1. On the first run, `sum` is the `initial` value (the last argument of `reduce`), equals `0`, and `current` is the first array element, equals `1`. So the function result is `1`. -2. On the second run, `sum = 1`, we add the second array element (`2`) to it and return. -3. On the 3rd run, `sum = 3` and we add one more element to it, and so on... +1. Ở lần chạy đầu tiên, `sum` là giá trị `ban đầu` (đối số cuối cùng của `reduce`), bằng `0` và `current` là phần tử array đầu tiên, bằng `1`. Vì vậy, kết quả hàm là `1`. +2. Ở lần chạy thứ hai, `sum = 1`, chúng ta thêm phần tử array thứ hai (`2`) vào nó và trả về. +3. Ở lần chạy thứ 3, `sum = 3` và chúng ta thêm một phần tử nữa vào nó, v.v... -The calculation flow: +Luồng tính toán: ![](reduce.svg) -Or in the form of a table, where each row represents a function call on the next array element: +Hoặc ở dạng bảng, trong đó mỗi hàng đại diện cho một lệnh gọi hàm trên phần tử array tiếp theo: -| |`sum`|`current`|result| -|---|-----|---------|---------| -|the first call|`0`|`1`|`1`| -|the second call|`1`|`2`|`3`| -|the third call|`3`|`3`|`6`| -|the fourth call|`6`|`4`|`10`| -|the fifth call|`10`|`5`|`15`| +| |`sum`|`current`|kết quả| +|---|-----|---------|-----| +|cuộc gọi đầu tiên|`0`|`1`|`1`| +|cuộc gọi thứ hai|`1`|`2`|`3`| +|cuộc gọi thứ ba|`3`|`3`|`6`| +|cuộc gọi thứ tư|`6`|`4`|`10`| +|cuộc gọi thứ năm|`10`|`5`|`15`| -Here we can clearly see how the result of the previous call becomes the first argument of the next one. +Ở đây chúng ta có thể thấy rõ kết quả của cuộc gọi trước đó trở thành đối số đầu tiên của cuộc gọi tiếp theo như thế nào. -We also can omit the initial value: +Chúng ta cũng có thể bỏ qua giá trị ban đầu: ```js run let arr = [1, 2, 3, 4, 5]; -// removed initial value from reduce (no 0) +// đã xóa giá trị ban đầu khỏi giảm (không có 0) let result = arr.reduce((sum, current) => sum + current); alert( result ); // 15 ``` -The result is the same. That's because if there's no initial, then `reduce` takes the first element of the array as the initial value and starts the iteration from the 2nd element. +Kết quả là như nhau. Đó là bởi vì nếu không có giá trị ban đầu, thì `reduce` sẽ lấy phần tử đầu tiên của array làm giá trị ban đầu và bắt đầu lặp lại từ phần tử thứ 2. -The calculation table is the same as above, minus the first row. +Bảng tính giống như trên, trừ hàng đầu tiên. -But such use requires an extreme care. If the array is empty, then `reduce` call without initial value gives an error. +Nhưng việc sử dụng như vậy đòi hỏi phải hết sức cẩn thận. Nếu array trống, thì lệnh gọi `reduce` không có giá trị ban đầu sẽ báo lỗi. -Here's an example: +Đây là một ví dụ: ```js run let arr = []; // Error: Reduce of empty array with no initial value -// if the initial value existed, reduce would return it for the empty arr. +// nếu giá trị ban đầu tồn tại, giảm sẽ trả lại nó cho array trống. arr.reduce((sum, current) => sum + current); ``` -So it's advised to always specify the initial value. +Vì vậy, nên luôn chỉ định giá trị ban đầu. -The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left. +Phương thức [arr.reduceRight](mdn:js/Array/reduceRight) cũng làm như vậy, nhưng đi từ phải sang trái. ## Array.isArray -Arrays do not form a separate language type. They are based on objects. +Các array không tạo thành một loại ngôn ngữ riêng biệt. Chúng dựa trên các đối tượng. -So `typeof` does not help to distinguish a plain object from an array: +Vì vậy, `typeof` không giúp phân biệt một đối tượng đơn giản với một arrray: ```js run -alert(typeof {}); // object -alert(typeof []); // same +alert(typeof {}); // đối tượng +alert(typeof []); // như nhau ``` -...But arrays are used so often that there's a special method for that: [Array.isArray(value)](mdn:js/Array/isArray). It returns `true` if the `value` is an array, and `false` otherwise. +...Nhưng array được sử dụng thường xuyên đến mức có một phương thức đặc biệt cho việc đó: [Array.isArray(value)](mdn:js/Array/isArray). Nó trả về `true` nếu `value` là một mảng và `false` nếu không. ```js run alert(Array.isArray({})); // false @@ -653,25 +653,25 @@ alert(Array.isArray({})); // false alert(Array.isArray([])); // true ``` -## Most methods support "thisArg" +## Hầu hết các phương thức đều hỗ trợ "thisArg" -Almost all array methods that call functions -- like `find`, `filter`, `map`, with a notable exception of `sort`, accept an optional additional parameter `thisArg`. +Hầu như tất cả các phương thức array gọi các hàm -- như `find`, `filter`, `map`, với một ngoại lệ đáng chú ý là `sort`, đều chấp nhận một tham số bổ sung tùy chọn `thisArg`. -That parameter is not explained in the sections above, because it's rarely used. But for completeness we have to cover it. +Tham số đó không được giải thích trong các phần trên, vì nó hiếm khi được sử dụng. Nhưng để hoàn thiện, chúng ta phải che đậy nó. -Here's the full syntax of these methods: +Đây là cú pháp đầy đủ của các phương thức này: ```js arr.find(func, thisArg); arr.filter(func, thisArg); arr.map(func, thisArg); // ... -// thisArg is the optional last argument +// thisArg là đối số cuối cùng tùy chọn ``` -The value of `thisArg` parameter becomes `this` for `func`. +Giá trị của tham số `thisArg` trở thành `this` cho `func`. -For example, here we use a method of `army` object as a filter, and `thisArg` passes the context: +Ví dụ: ở đây chúng ta sử dụng một phương thức của đối tượng `army` làm bộ lọc và `thisArg` chuyển ngữ cảnh: ```js run let army = { @@ -690,7 +690,7 @@ let users = [ ]; *!* -// find users, for who army.canJoin returns true +// tìm người dùng, cho những người army.canJoin trả về true let soldiers = users.filter(army.canJoin, army); */!* @@ -699,53 +699,53 @@ alert(soldiers[0].age); // 20 alert(soldiers[1].age); // 23 ``` -If in the example above we used `users.filter(army.canJoin)`, then `army.canJoin` would be called as a standalone function, with `this=undefined`, thus leading to an instant error. +Nếu trong ví dụ trên, chúng ta sử dụng `users.filter(army.canJoin)`, thì `army.canJoin` sẽ được gọi như một hàm độc lập, với `this=undefined`, do đó dẫn đến lỗi ngay lập tức. -A call to `users.filter(army.canJoin, army)` can be replaced with `users.filter(user => army.canJoin(user))`, that does the same. The latter is used more often, as it's a bit easier to understand for most people. +Lệnh gọi `users.filter(army.canJoin, army)` có thể được thay thế bằng `users.filter(user => army.canJoin(user))`, thao tác này cũng thực hiện tương tự. Cái sau được sử dụng thường xuyên hơn, vì nó dễ hiểu hơn đối với hầu hết mọi người. -## Summary +## Tóm tắt -A cheat sheet of array methods: +Một bảng hỗ trợ của các phương thức array: -- To add/remove elements: - - `push(...items)` -- adds items to the end, - - `pop()` -- extracts an item from the end, - - `shift()` -- extracts an item from the beginning, - - `unshift(...items)` -- adds items to the beginning. - - `splice(pos, deleteCount, ...items)` -- at index `pos` deletes `deleteCount` elements and inserts `items`. - - `slice(start, end)` -- creates a new array, copies elements from index `start` till `end` (not inclusive) into it. - - `concat(...items)` -- returns a new array: copies all members of the current one and adds `items` to it. If any of `items` is an array, then its elements are taken. +- Để thêm/bớt phần tử: + - `push(...items)` -- thêm các mục vào cuối, + - `pop()` -- trích xuất một mục từ cuối, + - `shift()` -- trích xuất một mục từ đầu, + - `unshift(...items)` -- thêm các mục vào đầu. + - `splice(pos, deleteCount, ...items)` -- tại chỉ mục `pos` xóa các phần tử `deleteCount` và chèn `items`. + - `slice(start, end)` -- tạo một array mới, sao chép các phần tử từ chỉ mục `start` cho đến `end` (không bao gồm) vào đó. + - `concat(...items)` -- trả về một array mới: sao chép tất cả các phần tử của array hiện tại và thêm `items` vào array đó. Nếu bất kỳ `item` nào là một array, thì các phần tử của array đó sẽ được lấy. -- To search among elements: - - `indexOf/lastIndexOf(item, pos)` -- look for `item` starting from position `pos`, return the index or `-1` if not found. - - `includes(value)` -- returns `true` if the array has `value`, otherwise `false`. - - `find/filter(func)` -- filter elements through the function, return first/all values that make it return `true`. - - `findIndex` is like `find`, but returns the index instead of a value. +- Tìm kiếm giữa các phần tử: + - `indexOf/lastIndexOf(item, pos)` -- tìm kiếm `item` bắt đầu từ vị trí `pos`, trả lại chỉ mục hoặc `-1` nếu không tìm thấy. + - `gồm(giá trị)` -- trả về `true` nếu array có `giá trị`, ngược lại là `false`. + - `find/filter(func)` -- lọc các phần tử thông qua hàm, trả về giá trị đầu tiên/tất cả khiến hàm trả về `true`. + - `findIndex` giống như `find`, nhưng trả về chỉ mục thay vì giá trị. -- To iterate over elements: - - `forEach(func)` -- calls `func` for every element, does not return anything. +- Để lặp qua các phần tử: + - `forEach(func)` -- gọi `func` cho mọi phần tử, không trả về bất kỳ thứ gì. -- To transform the array: - - `map(func)` -- creates a new array from results of calling `func` for every element. - - `sort(func)` -- sorts the array in-place, then returns it. - - `reverse()` -- reverses the array in-place, then returns it. - - `split/join` -- convert a string to array and back. - - `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls. +- Để biến đổi mảng: + - `map(func)` -- tạo một array mới từ kết quả gọi `func` cho mọi phần tử. + - `sort(func)` -- sắp xếp array tại chỗ, sau đó trả về array. + - `reverse()` -- đảo ngược array tại chỗ, sau đó trả về nó. + - `split/join` -- chuyển đổi một chuỗi thành array và ngược lại. + - `reduce/reduceRight(func, initial)` -- tính toán một giá trị duy nhất trên array bằng cách gọi `func` cho từng phần tử và chuyển kết quả trung gian giữa các lần gọi. -- Additionally: - - `Array.isArray(arr)` checks `arr` for being an array. +- Ngoài ra: + - `Array.isArray(arr)` kiểm tra `arr` có phải là một array hay không. -Please note that methods `sort`, `reverse` and `splice` modify the array itself. +Hãy lưu ý rằng các phương thức `sort`, `reverse` và `splice` tự sửa đổi array. -These methods are the most used ones, they cover 99% of use cases. But there are few others: +Những phương thức này là những phương thức được sử dụng nhiều nhất, chúng bao gồm 99% các trường hợp sử dụng. Nhưng có một số khác: -- [arr.some(fn)](mdn:js/Array/some)/[arr.every(fn)](mdn:js/Array/every) check the array. +- [arr.some(fn)](mdn:js/Array/some)/[arr.every(fn)](mdn:js/Array/every) kiểm tra array. - The function `fn` is called on each element of the array similar to `map`. If any/all results are `true`, returns `true`, otherwise `false`. + Hàm `fn` được gọi trên mỗi phần tử của array tương tự như `map`. Nếu bất kỳ/tất cả kết quả là `true`, trả về `true`, nếu không thì `false`. - These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well. + Các phương thức này hoạt động giống như các toán tử `||` và `&&`: nếu `fn` trả về một giá trị đúng, `arr.some()` ngay lập tức trả về `true` và ngừng lặp lại trên các mục còn lại; nếu `fn` trả về một giá trị giả, thì `arr.every()` sẽ ngay lập tức trả về `false` và cũng ngừng lặp lại trên các mục còn lại. - We can use `every` to compare arrays: + Chúng ta có thể sử dụng `every` để so sánh các array: ```js run function arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); @@ -754,16 +754,16 @@ These methods are the most used ones, they cover 99% of use cases. But there are alert( arraysEqual([1, 2], [1, 2])); // true ``` -- [arr.fill(value, start, end)](mdn:js/Array/fill) -- fills the array with repeating `value` from index `start` to `end`. +- [arr.fill(value, start, end)](mdn:js/Array/fill) -- lấp đầy array bằng cách lặp lại `value` từ chỉ mục `start` đến `end`. -- [arr.copyWithin(target, start, end)](mdn:js/Array/copyWithin) -- copies its elements from position `start` till position `end` into *itself*, at position `target` (overwrites existing). +- [arr.copyWithin(target, start, end)](mdn:js/Array/copyWithin) -- sao chép các phần tử của nó từ vị trí `start` cho đến vị trí `end` vào *chính nó*, tại vị trí `target` (ghi đè hiện có). -- [arr.flat(depth)](mdn:js/Array/flat)/[arr.flatMap(fn)](mdn:js/Array/flatMap) create a new flat array from a multidimensional array. +- [arr.flat(depth)](mdn:js/Array/flat)/[arr.flatMap(fn)](mdn:js/Array/flatMap) tạo một array phẳng mới từ một array nhiều chiều. -For the full list, see the [manual](mdn:js/Array). +Để biết danh sách đầy đủ, hãy xem [array](mdn:js/Array). -From the first sight it may seem that there are so many methods, quite difficult to remember. But actually that's much easier. +Ngay từ cái nhìn đầu tiên, có vẻ như có rất nhiều phương thức, khá khó nhớ. Nhưng thực ra điều đó dễ dàng hơn nhiều. -Look through the cheat sheet just to be aware of them. Then solve the tasks of this chapter to practice, so that you have experience with array methods. +Xem qua bảng hỗ trợ chỉ để biết về chúng. Sau đó giải quyết các nhiệm vụ của chương này để thực hành, để bạn có kinh nghiệm với các phương thức array. -Afterwards whenever you need to do something with an array, and you don't know how -- come here, look at the cheat sheet and find the right method. Examples will help you to write it correctly. Soon you'll automatically remember the methods, without specific efforts from your side. +Sau đó, bất cứ khi nào bạn cần làm gì đó với một array, và bạn không biết làm thế nào -- hãy đến đây, xem bảng hỗ trợ và tìm phương thức phù hợp. Ví dụ sẽ giúp bạn viết nó một cách chính xác. Bạn sẽ sớm tự động ghi nhớ các phương thức mà không cần nỗ lực cụ thể từ phía bạn.