diff --git a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/source.js b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/source.js index 5bf29aa2d..5638cfdfd 100644 --- a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/source.js +++ b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/_js.view/source.js @@ -1,7 +1,7 @@ function makeCounter() { let count = 0; - // ... your code ... + // ... mã của bạn ... } let counter = makeCounter(); @@ -9,10 +9,10 @@ let counter = makeCounter(); alert( counter() ); // 0 alert( counter() ); // 1 -counter.set(10); // set the new count +counter.set(10); // đặt số lượng đếm mới alert( counter() ); // 10 -counter.decrease(); // decrease the count by 1 +counter.decrease(); // giảm số lượng đi 1 -alert( counter() ); // 10 (instead of 11) +alert( counter() ); // 10 (thay vì 11) diff --git a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/solution.md b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/solution.md index e829d96ee..1e65ae140 100644 --- a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/solution.md +++ b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/solution.md @@ -1,2 +1,2 @@ -The solution uses `count` in the local variable, but addition methods are written right into the `counter`. They share the same outer lexical environment and also can access the current `count`. +Giải pháp sử dụng `count` trong biến cục bộ, nhưng các phương thức bổ sung được viết ngay vào `counter`. Chúng chia sẻ cùng một lexical environment bên ngoài và cũng có thể truy cập `count` hiện tại. diff --git a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md index a11821d67..505e19dd7 100644 --- a/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md +++ b/1-js/06-advanced-functions/06-function-object/2-counter-inc-dec/task.md @@ -2,14 +2,14 @@ importance: 5 --- -# Set and decrease for counter +# Đặt và giảm cho bộ đếm -Modify the code of `makeCounter()` so that the counter can also decrease and set the number: +Sửa đổi mã của `makeCounter()` để bộ đếm cũng có thể giảm và đặt số: -- `counter()` should return the next number (as before). -- `counter.set(value)` should set the counter to `value`. -- `counter.decrease()` should decrease the counter by 1. +- `counter()` nên trả lại số tiếp theo (như trước). +- `counter.set(value)` nên đặt bộ đếm thành `value`. +- `counter.decrease()` nên giảm của bộ đếm 1 đơn vị. -See the sandbox code for the complete usage example. +Xem mã sandbox để biết ví dụ sử dụng đầy đủ. -P.S. You can use either a closure or the function property to keep the current count. Or write both variants. +Tái bút: Bạn có thể sử dụng bao đóng hoặc thuộc tính hàm để giữ số lượng hiện tại. Hoặc viết cả hai biến thể. diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md index e97039f72..d4dd1b193 100644 --- a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md @@ -1,9 +1,9 @@ -1. For the whole thing to work *anyhow*, the result of `sum` must be function. -2. That function must keep in memory the current value between calls. -3. According to the task, the function must become the number when used in `==`. Functions are objects, so the conversion happens as described in the chapter , and we can provide our own method that returns the number. +1. Để toàn bộ hoạt động *dù sao đi nữa*, kết quả của `sum` phải là hàm. +2. Hàm đó phải giữ trong bộ nhớ giá trị hiện tại giữa các cuộc gọi. +3. Theo nhiệm vụ, hàm phải trở thành số khi được sử dụng trong `==`. Các hàm là các đối tượng, vì vậy việc chuyển đổi diễn ra như được mô tả trong chương và chúng ta có thể cung cấp phương thức trả về số của riêng mình. -Now the code: +Bây giờ là mã: ```js demo run function sum(a) { @@ -28,28 +28,28 @@ alert( sum(6)(-1)(-2)(-3) ); // 0 alert( sum(0)(1)(2)(3)(4)(5) ); // 15 ``` -Please note that the `sum` function actually works only once. It returns function `f`. +Hãy lưu ý rằng chức năng `sum` thực sự chỉ hoạt động một lần. Nó trả về hàm `f`. -Then, on each subsequent call, `f` adds its parameter to the sum `currentSum`, and returns itself. +Sau đó, trong mỗi lệnh gọi tiếp theo, `f` thêm tham số của nó vào tổng `currentSum` và trả về chính nó. -**There is no recursion in the last line of `f`.** +**Không có đệ quy trong dòng cuối cùng của `f`.** -Here is what recursion looks like: +Đây là những gì đệ quy trông giống: ```js function f(b) { currentSum += b; - return f(); // <-- recursive call + return f(); // <-- cuộc gọi đệ quy } ``` -And in our case, we just return the function, without calling it: +Và trong trường hợp của chúng ta, chúng ta chỉ trả về hàm mà không gọi nó: ```js function f(b) { currentSum += b; - return f; // <-- does not call itself, returns itself + return f; // <-- không tự gọi, tự trả về } ``` -This `f` will be used in the next call, again return itself, as many times as needed. Then, when used as a number or a string -- the `toString` returns the `currentSum`. We could also use `Symbol.toPrimitive` or `valueOf` here for the conversion. +`f` này sẽ được sử dụng trong lần gọi tiếp theo, một lần nữa sẽ tự trả về chính nó, nhiều lần nếu cần. Sau đó, khi được sử dụng làm số hoặc chuỗi -- `toString` trả về `currentSum`. Chúng ta cũng có thể sử dụng `Symbol.toPrimitive` hoặc `valueOf` tại đây để chuyển đổi. diff --git a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md index dc13f260b..fa3ecb521 100644 --- a/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md +++ b/1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/task.md @@ -2,9 +2,9 @@ importance: 2 --- -# Sum with an arbitrary amount of brackets +# Tổng với số lượng dấu ngoặc tùy ý -Write function `sum` that would work like this: +Viết hàm `sum` sẽ hoạt động như thế này: ```js sum(1)(2) == 3; // 1 + 2 @@ -14,4 +14,5 @@ sum(6)(-1)(-2)(-3) == 0 sum(0)(1)(2)(3)(4)(5) == 15 ``` -P.S. Hint: you may need to setup custom object to primitive conversion for your function. \ No newline at end of file +Tái bút: +Gợi ý: Bạn có thể cần thiết lập đối tượng tùy chỉnh thành chuyển đổi nguyên thủy cho hàm của mình. diff --git a/1-js/06-advanced-functions/06-function-object/article.md b/1-js/06-advanced-functions/06-function-object/article.md index 12342f45a..24278a821 100644 --- a/1-js/06-advanced-functions/06-function-object/article.md +++ b/1-js/06-advanced-functions/06-function-object/article.md @@ -1,20 +1,20 @@ -# Function object, NFE +# Đối tượng hàm, NFE -As we already know, a function in JavaScript is a value. +Như chúng ta đã biết, một hàm trong JavaScript là một giá trị. -Every value in JavaScript has a type. What type is a function? +Mọi giá trị trong JavaScript đều có một loại. Hàm là loại gì? -In JavaScript, functions are objects. +Trong JavaScript, hàm là đối tượng. -A good way to imagine functions is as callable "action objects". We can not only call them, but also treat them as objects: add/remove properties, pass by reference etc. +Một cách hay để tưởng tượng các chức năng là "đối tượng hành động" có thể gọi được. Chúng ta không chỉ có thể gọi chúng mà còn coi chúng như các đối tượng: thêm/xóa thuộc tính, chuyển qua tham chiếu, v.v. -## The "name" property +## Thuộc tính "name" -Function objects contain some useable properties. +Các đối tượng chức năng chứa một số thuộc tính có thể sử dụng được. -For instance, a function's name is accessible as the "name" property: +Chẳng hạn, tên của hàm có thể truy cập dưới dạng thuộc tính "name": ```js run function sayHi() { @@ -24,29 +24,29 @@ function sayHi() { alert(sayHi.name); // sayHi ``` -What's kind of funny, the name-assigning logic is smart. It also assigns the correct name to a function even if it's created without one, and then immediately assigned: +Thật buồn cười, logic gán tên thật thông minh. Nó cũng gán tên chính xác cho một hàm ngay cả khi nó được tạo mà không có tên, và sau đó được gán ngay lập tức: ```js run let sayHi = function() { alert("Hi"); }; -alert(sayHi.name); // sayHi (there's a name!) +alert(sayHi.name); // sayHi (có một cái tên!) ``` -It also works if the assignment is done via a default value: +Nó cũng hoạt động nếu việc gán được thực hiện thông qua một giá trị mặc định: ```js run function f(sayHi = function() {}) { - alert(sayHi.name); // sayHi (works!) + alert(sayHi.name); // sayHi (hoạt động!) } f(); ``` -In the specification, this feature is called a "contextual name". If the function does not provide one, then in an assignment it is figured out from the context. +Trong thông số kỹ thuật, tính năng này được gọi là "tên theo ngữ cảnh". Nếu hàm không cung cấp một hàm, thì trong một nhiệm vụ, nó được tìm ra từ ngữ cảnh. -Object methods have names too: +Các phương thức đối tượng cũng có tên: ```js run let user = { @@ -65,46 +65,46 @@ alert(user.sayHi.name); // sayHi alert(user.sayBye.name); // sayBye ``` -There's no magic though. There are cases when there's no way to figure out the right name. In that case, the name property is empty, like here: +Tuy nhiên, không có phép thuật đâu. Có những trường hợp không có cách nào để tìm ra tên đúng. Trong trường hợp đó, thuộc tính name trống, như ở đây: ```js run -// function created inside array +// hàm được tạo bên trong array let arr = [function() {}]; alert( arr[0].name ); // -// the engine has no way to set up the right name, so there is none +// engine không có cách nào để thiết lập đúng tên, vì vậy không có tên ``` -In practice, however, most functions do have a name. +Tuy nhiên, trong thực tế, hầu hết các hàm đều có tên. -## The "length" property +## Thuộc tính "length" -There is another built-in property "length" that returns the number of function parameters, for instance: +có một thuộc tính tích hợp sẵn khác là "length" trả về số lượng tham số hàm, vídu5: ```js run function f1(a) {} function f2(a, b) {} -function many(a, b, ...more) {} +function many(a, b, ...hơn nữa) {} alert(f1.length); // 1 alert(f2.length); // 2 alert(many.length); // 2 ``` -Here we can see that rest parameters are not counted. +Ở đây chúng ta có thể thấy rằng các tham số còn lại không được tính. -The `length` property is sometimes used for [introspection](https://en.wikipedia.org/wiki/Type_introspection) in functions that operate on other functions. +Thuộc tính `length` đôi khi được sử dụng cho [tự xét](https://en.wikipedia.org/wiki/Type_introspection) trong các hàm hoạt động trên các hàm khác. -For instance, in the code below the `ask` function accepts a `question` to ask and an arbitrary number of `handler` functions to call. +Chẳng hạn, trong mã bên dưới, hàm `ask` chấp nhận một `question` để hỏi và một số hàm `handlers` tùy ý để gọi. -Once a user provides their answer, the function calls the handlers. We can pass two kinds of handlers: +Khi người dùng cung cấp câu trả lời của họ, hàm sẽ gọi trình xử lý. Chúng ta có thể vượt qua hai loại trình xử lý: -- A zero-argument function, which is only called when the user gives a positive answer. -- A function with arguments, which is called in either case and returns an answer. +- Hàm không đối số, chỉ được gọi khi người dùng đưa ra câu trả lời khẳng định. +- Hàm có đối số, được gọi trong cả hai trường hợp và trả về câu trả lời. -To call `handler` the right way, we examine the `handler.length` property. +Để gọi `handler` đúng cách, chúng ta kiểm tra thuộc tính `handler.length`. -The idea is that we have a simple, no-arguments handler syntax for positive cases (most frequent variant), but are able to support universal handlers as well: +Ý tưởng là chúng ta có một cú pháp trình xử lý đơn giản, không có đối số cho các trường hợp khẳng định (biến thể phổ biến nhất), nhưng cũng có thể hỗ trợ các trình xử lý chung: ```js run function ask(question, ...handlers) { @@ -120,47 +120,47 @@ function ask(question, ...handlers) { } -// for positive answer, both handlers are called -// for negative answer, only the second one -ask("Question?", () => alert('You said yes'), result => alert(result)); +// đối với câu trả lời khẳng định, cả hai trình xử lý được gọi +// đối với câu trả lời phủ định, chỉ gọi cái thứ hai +ask("Câu hỏi?", () => alert('Bạn nói có'), result => alert(result)); ``` -This is a particular case of so-called [polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) -- treating arguments differently depending on their type or, in our case depending on the `length`. The idea does have a use in JavaScript libraries. +Đây là một trường hợp cụ thể của cái gọi là [đa hình](https://vi.wikipedia.org/wiki/%C4%90a_h%C3%ACnh_(khoa_h%E1%BB%8Dc_m%C3%A1y_t%C3%ADnh)) -- xử lý các đối số khác nhau tùy thuộc vào loại của chúng hoặc, trong trường hợp của chúng ta, tùy thuộc vào `length`. Ý tưởng này được sử dụng trong các thư viện JavaScript. -## Custom properties +## Thuộc tính tùy chỉnh -We can also add properties of our own. +Chúng ta cũng có thể thêm các thuộc tính của riêng mình. -Here we add the `counter` property to track the total calls count: +Ở đây chúng ta thêm thuộc tính `counter` để theo dõi tổng số cuộc gọi: ```js run function sayHi() { - alert("Hi"); + alert("Chào"); *!* - // let's count how many times we run + // hãy đếm xem chúng ta chạy bao nhiêu lần sayHi.counter++; */!* } -sayHi.counter = 0; // initial value +sayHi.counter = 0; // giá trị ban đầu -sayHi(); // Hi -sayHi(); // Hi +sayHi(); // Chào +sayHi(); // Chào -alert( `Called ${sayHi.counter} times` ); // Called 2 times +alert( `Đã gọi ${sayHi.counter} lần` ); // Đã gọi 2 lần ``` -```warn header="A property is not a variable" -A property assigned to a function like `sayHi.counter = 0` does *not* define a local variable `counter` inside it. In other words, a property `counter` and a variable `let counter` are two unrelated things. +```warn header="Một thuộc tính không phải là một biến" +Một thuộc tính được gán cho một hàm như `sayHi.counter = 0` *không* xác định một biến chung `counter` bên trong nó. Nói cách khác, một thuộc tính `counter` và một biến `let counter` là hai thứ không liên quan đến nhau. -We can treat a function as an object, store properties in it, but that has no effect on its execution. Variables are not function properties and vice versa. These are just parallel worlds. +Chúng ta có thể coi một hàm như một đối tượng, lưu trữ các thuộc tính trong đó, nhưng điều đó không ảnh hưởng đến việc thực thi của nó. Các biến không phải là thuộc tính của hàm và ngược lại. Đây chỉ là những thế giới song song. ``` -Function properties can replace closures sometimes. For instance, we can rewrite the counter function example from the chapter to use a function property: +Các thuộc tính chức năng đôi khi có thể thay thế các bao đóng. Chẳng hạn, chúng ta có thể viết lại ví dụ về hàm bộ đếm từ chương để sử dụng thuộc tính hàm: ```js run function makeCounter() { - // instead of: + // thay vì: // let count = 0 function counter() { @@ -177,11 +177,11 @@ alert( counter() ); // 0 alert( counter() ); // 1 ``` -The `count` is now stored in the function directly, not in its outer Lexical Environment. +`count` hiện được lưu trữ trực tiếp trong hàm, không phải ở Lexical Environment bên ngoài của nó. -Is it better or worse than using a closure? +Nó tốt hơn hay tệ hơn việc sử dụng một bao đóng? -The main difference is that if the value of `count` lives in an outer variable, then external code is unable to access it. Only nested functions may modify it. And if it's bound to a function, then such a thing is possible: +Sự khác biệt chính là nếu giá trị của `count` tồn tại trong một biến bên ngoài, thì mã bên ngoài không thể truy cập vào biến đó. Chỉ các hàm lồng nhau mới có thể sửa đổi nó. Và nếu nó bị ràng buộc với một hàm, thì điều đó có thể xảy ra: ```js run function makeCounter() { @@ -203,13 +203,13 @@ alert( counter() ); // 10 */!* ``` -So the choice of implementation depends on our aims. +Vì vậy, việc lựa chọn thực hiện phụ thuộc vào mục tiêu của chúng ta. ## Named Function Expression -Named Function Expression, or NFE, is a term for Function Expressions that have a name. +Named Function Expression, hay NFE, là một thuật ngữ cho Function Expression có tên. -For instance, let's take an ordinary Function Expression: +Chẳng hạn, hãy lấy một Function Expression thông thường: ```js let sayHi = function(who) { @@ -217,80 +217,80 @@ let sayHi = function(who) { }; ``` -And add a name to it: +Và thêm một cái tên cho nó: ```js let sayHi = function *!*func*/!*(who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); }; ``` -Did we achieve anything here? What's the purpose of that additional `"func"` name? +Chúng ta đã đạt được bất cứ điều gì ở đây? Mục đích của tên `"func"` bổ sung đó là gì? -First let's note, that we still have a Function Expression. Adding the name `"func"` after `function` did not make it a Function Declaration, because it is still created as a part of an assignment expression. +Trước tiên, hãy lưu ý rằng chúng ta vẫn có một Function Expression. Việc thêm tên `"func"` sau `function` không làm cho nó trở thành một Function Declaration, bởi vì nó vẫn được tạo như một phần của biểu thức gán. -Adding such a name also did not break anything. +Thêm một tên như vậy cũng không phá vỡ bất cứ điều gì. -The function is still available as `sayHi()`: +Chức năng này vẫn có sẵn dưới dạng `sayHi()`: ```js run let sayHi = function *!*func*/!*(who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); }; -sayHi("John"); // Hello, John +sayHi("John"); // Xin chào, John ``` -There are two special things about the name `func`, that are the reasons for it: +Có hai điều đặc biệt về cái tên `func`, đó là lý do của nó: -1. It allows the function to reference itself internally. -2. It is not visible outside of the function. +1. Nó cho phép hàm tự tham chiếu nội bộ. +2. Nó không nhìn thấy được bên ngoài hàm. -For instance, the function `sayHi` below calls itself again with `"Guest"` if no `who` is provided: +Chẳng hạn, hàm `sayHi` bên dưới tự gọi lại bằng `"Khách"` nếu không cung cấp `who`: ```js run let sayHi = function *!*func*/!*(who) { if (who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); } else { *!* - func("Guest"); // use func to re-call itself + func("Khách"); // sử dụng func để gọi lại chính nó */!* } }; -sayHi(); // Hello, Guest +sayHi(); // Xin chào,Khách -// But this won't work: -func(); // Error, func is not defined (not visible outside of the function) +// Nhưng cái này sẽ không hoạt động: +func(); // Error, func is not defined (không hiển thị bên ngoài hàm) ``` -Why do we use `func`? Maybe just use `sayHi` for the nested call? +Tại sao chúng ta sử dụng `func`? Có lẽ chỉ cần sử dụng `sayHi` cho cuộc gọi lồng nhau? -Actually, in most cases we can: +Trên thực tế, trong hầu hết các trường hợp, chúng ta có thể: ```js let sayHi = function(who) { if (who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); } else { *!* - sayHi("Guest"); + sayHi("Khách"); */!* } }; ``` -The problem with that code is that `sayHi` may change in the outer code. If the function gets assigned to another variable instead, the code will start to give errors: +Vấn đề với mã đó là `sayHi` có thể thay đổi ở mã bên ngoài. Nếu hàm được gán cho một biến khác, mã sẽ bắt đầu báo lỗi: ```js run let sayHi = function(who) { if (who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); } else { *!* - sayHi("Guest"); // Error: sayHi is not a function + sayHi("Khách"); // Error: sayHi is not a function */!* } }; @@ -301,19 +301,19 @@ sayHi = null; welcome(); // Error, the nested sayHi call doesn't work any more! ``` -That happens because the function takes `sayHi` from its outer lexical environment. There's no local `sayHi`, so the outer variable is used. And at the moment of the call that outer `sayHi` is `null`. +Điều đó xảy ra bởi vì hàm lấy `sayHi` từ lexical environment bên ngoài của nó. Không có `sayHi` cục bộ, vì vậy biến bên ngoài được sử dụng. Và tại thời điểm gọi, `sayHi` bên ngoài là `null`. -The optional name which we can put into the Function Expression is meant to solve exactly these kinds of problems. +Tên tùy chọn mà chúng ta có thể đặt vào Function Expression nhằm giải quyết chính xác các loại vấn đề này. -Let's use it to fix our code: +Hãy sử dụng nó để sửa mã của chúng ta: ```js run let sayHi = function *!*func*/!*(who) { if (who) { - alert(`Hello, ${who}`); + alert(`Xin chào, ${who}`); } else { *!* - func("Guest"); // Now all fine + func("Khách"); // Bây giờ tất cả đều ổn */!* } }; @@ -321,33 +321,33 @@ let sayHi = function *!*func*/!*(who) { let welcome = sayHi; sayHi = null; -welcome(); // Hello, Guest (nested call works) +welcome(); // Xin chào, Khách (cuộc gọi lồng nhau hoạt động) ``` -Now it works, because the name `"func"` is function-local. It is not taken from outside (and not visible there). The specification guarantees that it will always reference the current function. +Bây giờ nó hoạt động, bởi vì tên `"func"` là chức năng cục bộ. Nó không được lấy từ bên ngoài (và không nhìn thấy ở đó). Thông số kỹ thuật đảm bảo rằng nó sẽ luôn tham chiếu đến hàm hiện tại. -The outer code still has its variable `sayHi` or `welcome`. And `func` is an "internal function name", how the function can call itself internally. +Mã bên ngoài vẫn có biến `sayHi` hoặc `welcome` của nó. Và `func` là một "tên hàm nội bộ", làm thế nào hàm có thể gọi chính nó trong nội bộ. -```smart header="There's no such thing for Function Declaration" -The "internal name" feature described here is only available for Function Expressions, not for Function Declarations. For Function Declarations, there is no syntax for adding an "internal" name. +```smart header="Không có điều đó cho Function Declaration" +Tính năng "tên nội bộ" được mô tả ở đây chỉ khả dụng cho Function Expression, không dành cho Function Declaration. Đối với Function Declaration, không có cú pháp nào để thêm tên "nội bộ". -Sometimes, when we need a reliable internal name, it's the reason to rewrite a Function Declaration to Named Function Expression form. +Đôi khi, khi chúng ta cần một tên nội bộ đáng tin cậy, đó là lý do để viết lại một Function Declaration thành kiểu Named Function Expression. ``` -## Summary +## Tóm tắt -Functions are objects. +Hàm là đối tượng. -Here we covered their properties: +Ở đây chúng ta đã đề cập đến các thuộc tính của chúng: -- `name` -- the function name. Usually taken from the function definition, but if there's none, JavaScript tries to guess it from the context (e.g. an assignment). -- `length` -- the number of arguments in the function definition. Rest parameters are not counted. +- `name` -- tên chức năng. Thường được lấy từ định nghĩa hàm, nhưng nếu không có, JavaScript sẽ cố gắng đoán nó từ ngữ cảnh (ví dụ: một nhiệm vụ). +- `length` -- số lượng đối số trong định nghĩa hàm. Các thông số còn lại không được tính. -If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called a Named Function Expression. The name can be used inside to reference itself, for recursive calls or such. +Nếu hàm được khai báo là Function Expression (không có trong luồng mã chính) và hàm mang tên, thì nó được gọi là Named Function Expression. Tên có thể được sử dụng bên trong để tham chiếu chính nó, cho các cuộc gọi đệ quy hoặc tương tự. -Also, functions may carry additional properties. Many well-known JavaScript libraries make great use of this feature. +Ngoài ra, các hàm có thể mang các thuộc tính bổ sung. Nhiều thư viện JavaScript nổi tiếng sử dụng rất tốt tính năng này. -They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`, and then adds `_.clone`, `_.keyBy` and other properties to it (see the [docs](https://lodash.com/docs) when you want to learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts. +Họ tạo một chức năng "chính" và đính kèm nhiều chức năng "trợ giúp" khác cho nó. Chẳng hạn, thư viện [jQuery](https://jquery.com) tạo một hàm có tên `$`. Thư viện [lodash](https://lodash.com) tạo một hàm `_`, sau đó thêm `_.clone`, `_.keyBy` và các thuộc tính khác vào hàm đó (xem [tài liệu](https:/ /lodash.com/docs) khi bạn muốn tìm hiểu thêm về chúng). Trên thực tế, họ làm điều đó để giảm bớt ô nhiễm không gian chung, do đó, một thư viện duy nhất chỉ cung cấp một biến chung. Điều đó làm giảm khả năng đặt tên xung đột. -So, a function can do a useful job by itself and also carry a bunch of other functionality in properties. +Vì vậy, một chức năng có thể tự thực hiện một công việc hữu ích và cũng mang theo một loạt các hàm khác trong các thuộc tính.