From dc5589711775e8fd02a13784f6e846bf86022152 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 5 Oct 2017 21:56:41 +0700 Subject: [PATCH 01/78] VN translate to VN --- 1-js/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/index.md b/1-js/index.md index c313cb85c8..fd8fdf706a 100644 --- a/1-js/index.md +++ b/1-js/index.md @@ -1,6 +1,6 @@ -# The JavaScript language +# Ngôn ngữ lập trình JavaScript -Here we learn JavaScript, starting from scratch and go on to advanced concepts like OOP. +Chúng ta sẽ học JavaScript, từ đầu cho đến các khái niệm nâng cao như lập trình hướng đối tượng (OOP). -We concentrate on the language itself here, with the minimum of environment-specific notes. +Ở đây sẽ tập trung vào học ngôn ngữ là chính, về môi trường (environment), editor, ... và các thứ linh tinh phụ trợ sẽ không nói đến, trừ trường hợp cần thiết. From 2932e38e61806bf7573741d63db9422cfb39dda4 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 5 Oct 2017 21:58:05 +0700 Subject: [PATCH 02/78] vn vn --- 1-js/01-getting-started/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/01-getting-started/index.md b/1-js/01-getting-started/index.md index b327c78603..abd705d1d4 100644 --- a/1-js/01-getting-started/index.md +++ b/1-js/01-getting-started/index.md @@ -1,3 +1,3 @@ -# An introduction +# Lời giới thiệu -About the JavaScript language and the environment to develop with it. +Về ngôn ngữ JavaScript và môi trường phát triển. From ca0dfda60325ec8d053022bd0b08a659566be7dc Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 5 Oct 2017 22:31:07 +0700 Subject: [PATCH 03/78] VN VN --- 1-js/01-getting-started/1-intro/article.md | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index 1e2e97d70c..4a900d652e 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -1,40 +1,40 @@ -# An Introduction to JavaScript +# Giới thiệu về ngôn ngữ JavaScript -Let's see what's so special about JavaScript, what we can achieve with it and which other technologies play well with it. +Hãy xem những điểm đặc biệt về JavaScript, và chúng ta sẽ làm được gì với JavaScript. -## What is JavaScript? +## JavaScript là cái méo gì? -*JavaScript* was initially created to *"make webpages alive"*. +*JavaScript* ban đầu được tạo ra để *"Làm cho trang web sống động hơn (make webpages alive)"*. -The programs in this language are called *scripts*. They can be written right in the HTML and execute automatically as the page loads. +Các chương trình trong ngôn ngữ này được gọi là *kịch bản(scripts)*. Chúng được nhúng trong HTML và được thực thi một cách tự động khi trang web được tải. -Scripts are provided and executed as a plain text. They don't need a special preparation or a compilation to run. +Scripts được viết và thực thi như văn bản thuần túy (plain text) mà không cần trình biên dịch, hay bất cứ sự chuẩn bị nào như các ngôn ngữ lập trình khác. -In this aspect, JavaScript is very different from another language called [Java](http://en.wikipedia.org/wiki/Java). +Về khía cạnh này, JavaScript rất khác với [Java](http://en.wikipedia.org/wiki/Java). -```smart header="Why JavaScript?" -When JavaScript was created, it initially had another name: "LiveScript". But Java language was very popular at that time, so it was decided that positioning a new language as a "younger brother" of Java would help. +```smart header="Tại sao là JavaScript?" +Khi JavaScript được tạo ra, ban đầu nó có tên là "LiveScript". Nhưng tại thời điểm đó, ngôn ngữ Java đang rất thông dụng và nổi tiếng, vì vậy nó được đặt lại tên là JavaSctips để ăn hôi tên tuổi của Java. Này gọi là thấy sang bắt quàng làm họ ấy mà. -But as it evolved, JavaScript became a fully independent language, with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all. +Nhưng khi phát triển, JavaScript đã trở thành một ngôn ngữ hoàn toàn độc lập, với các đặc tả riêng được gọi là [ECMAScript ](http://en.wikipedia.org/wiki/ECMAScript), và nói chung thì JavaScript và Java chẳng có liên quan gì đến nhau. ``` -At present, JavaScript can execute not only in the browser, but also on the server, or actually on any device where there exists a special program called [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine). +Hiện nay, JavaScript không chỉ chạy trên trình duyệt (front-end), mà còn chạy được trên máy chủ (back-end), hoặc trên bất kỳ thiết bị nào có hỗ trợ một chương trình đặc biệt được gọi nôm na là cỗ máy JavaScript [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine). -The browser has an embedded engine, sometimes it's also called a "JavaScript virtual machine". +Trên trình duyệt bạn sử dụng như Chrome, FireFox, Edge...đã nhúng sẵn JavaScript Engine rồi, đôi lúc người ta cũng hay gọi là "JavaScript virtual machine" (Máy ảo JavaScript) - Dịch ra nghe chuối VCL -Different engines have different "codenames", for example: +Engine nó cũng có nhiều loại. Mỗi engines khác nhau lại có "kiểu code" khác nhau, Ví dụ: -- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera. -- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox. -- ...There are other codenames like "Trident", "Chakra" for different versions of IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari etc. +- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- trên Chrome và Opera. +- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- trên Firefox. +- ...và một số engine khác như "Trident", "Chakra" cho các phiên bản IE, "ChakraCore" cho Microsoft Edge, "Nitro" và "SquirrelFish" cho Safari, vân vân. -The terms above are good to remember, because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera. +Nên nhớ những điều trên nhé, bởi vì có khi cần dùng hoặc debug. Ví dụ "tính năng X nào đó được hỗ trợ bởi Engine V8", thì sẽ chạy được trên Chrome và Opera. -```smart header="How engines work?" +```smart header="engines hoạt động như thế nào?" Engines are complicated. But the basics are easy. -1. The engine (embedded if it's a browser) reads ("parses") the script. +1. Engine (embedded if it's a browser) đọc và phân tích code của bạn. 2. Then it converts ("compiles") the script to the machine language. 3. And then the machine code runs, pretty fast. From d01a039330ea3aa164256dfddca6a66917704185 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 5 Oct 2017 23:29:34 +0700 Subject: [PATCH 04/78] vn vn --- 1-js/01-getting-started/1-intro/article.md | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index 4a900d652e..babaf9fa3f 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -32,43 +32,43 @@ Nên nhớ những điều trên nhé, bởi vì có khi cần dùng hoặc debu ```smart header="engines hoạt động như thế nào?" -Engines are complicated. But the basics are easy. +Để tìm hiểu sâu về Engine thì phức tạp vãi lúa. Nhưng nôm na thì có ba bước cơ bản sau khi bạn chạy code. -1. Engine (embedded if it's a browser) đọc và phân tích code của bạn. -2. Then it converts ("compiles") the script to the machine language. -3. And then the machine code runs, pretty fast. +1. Engine đọc và phân tích code của bạn. +2. Biên dịch code sang ngôn ngữ máy. +3. Và chạy thôi. Khá là nhanh. -The engine applies optimizations on every stage of the process. It even watches the compiled script as it runs, analyzes the data that flows through it and applies optimizations to the machine code based on that knowledge. At the end, scripts are quite fast. +Quá trình này được Engine tối ưu hóa theo từng giai đoạn bên trên. Nó theo dõi code được biên dịch và chạy như thế nào, phân tích các dữ liệu này để tối ưu. Cuối cùng thì cho ra kết quả là code JavaScript thường chạy rất là nhanh. ``` -## What can in-browser JavaScript do? +## JavaScript trên trình duyệt Web có thể làm gì? -The modern JavaScript is a "safe" programming language. It does not provide low-level access to memory or CPU, because it was initially created for browsers which do not require it. +JavaScript là một ngôn ngữ an toàn. Nó không cho truy nhập vào CPU và bộ nhớ máy, bởi vì ban đầu nó được tạo ra để chỉ làm việc với trình duyệt Web. -The capabilities greatly depend on the environment that runs JavaScript. For instance, [Node.JS](https://wikipedia.org/wiki/Node.js) supports functions that allow JavaScript to read/write arbitrary files, perform network requests etc. +Khả năng của JavaScript phụ thuộc rất nhiều vào môi trường chạy JavaScript. Ví dụ, , [Node.JS](https://wikipedia.org/wiki/Node.js) hỗ trợ các chức năng cho phép JavaScript đọc / ghi các tập tin tùy ý, thực hiện các yêu cầu mạng, vv -In-browser JavaScript can do everything related to webpage manipulation, interaction with the user and the webserver. +Trên trình duyệt Web, JavaScript có thể làm bất cứ thứ gì liên quan đến trang web, cũng như tương tác với người dùng và máy chủ Web. -For instance, in-browser JavaScript is able to: +Ví dụ, trên trình duyệt JavaScript có thể: -- Add new HTML to the page, change the existing content, modify styles. -- React to user actions, run on mouse clicks, pointer movements, key presses. -- Send requests over the network to remote servers, download and upload files (so-called [AJAX](https://en.wikipedia.org/wiki/Ajax_(programming)) and [COMET](https://en.wikipedia.org/wiki/Comet_(programming)) technologies). -- Get and set cookies, ask questions to the visitor, show messages. -- Remember the data on the client-side ("local storage"). +- Tạo các thẻ HTML vào trang web, thay đổi nội dung, chỉnh sửa styles. +- Phản hồi các thao tác của người dùng, chạy các hành động khi click chuột, di chuyển con trỏ, nhấn phím. +- Gửi các yêu cầu đến máy chủ nào đó qua mạng, download và upload files (Cái mà người ta hay gọi là [AJAX](https://en.wikipedia.org/wiki/Ajax_(programming)) và [COMET](https://en.wikipedia.org/wiki/Comet_(programming)) ). +- Truy vấn và cài đặt cookies, hỏi người dùng vài câu hỏi, đưa ra các thông báo trên trang web.... +- Lưu trữ dữ liệu (username, password, form mẫu....) trên trình duyệt Web của bạn. -## What CAN'T in-browser JavaScript do? +## JavaScript không thể làm được gì trên trình duyệt Web? -JavaScript's abilities in the browser are limited for the sake of the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data. +Khả năng của JavaScript trong trình duyệt được giới hạn vì sự an toàn của người dùng. Mục đích là để ngăn chặn các trang web độc hại truy cập thông tin cá nhân hoặc đánh cắp dữ liệu của người dùng. -The examples of such restrictions are: +Ví dụ: -- JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs. It has no direct access to OS system functions. +- JavaScript trên Website không thể đọc / ghi / copy các tập tin trên ổ đĩa, không thể thực thi các chương trình. Và không có quyền truy cập trực tiếp vào các chức năng của hệ điều hành. - Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `` tag. + Các trình duyệt hiện đại cho phép JavaScript làm việc với các tệp, nhưng quyền truy cập bị hạn chế và chỉ được cung cấp nếu người dùng thực hiện các hành động nhất định, như kéo-thả (dropping) một file vào cửa sổ trình duyệt hoặc chọn file qua thẻ ``. - There are ways to interact with camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency). -- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port). + Có nhiều cách để tương tác với webcam/ camera/ micro và các thiết bị khác nhưng chúng cần có sự cho phép rõ ràng của người dùng. Vì vậy, một trang Web kích hoạt JavaScript không thể lén kích hoạt webcam, ghi hình và gửi thông tin cho [NSA](https://en.wikipedia.org/wiki/National_Security_Agency). +- Các tabs/windows không nhận biết lẫn nhau. Kể cả trong trường hợp từ Tab này bạn chạy JavaScript mở ra một tab khác. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port). This is called the "Same Origin Policy". To work around that, *both pages* must contain a special JavaScript code that handles data exchange. From bdcffceb63382c8edec486aef16fc41ace2a3d91 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 15:16:37 +0700 Subject: [PATCH 05/78] translate to VN translate to VN --- 1-js/01-getting-started/1-intro/article.md | 55 ++++++++++------------ 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index babaf9fa3f..f493f55c90 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -68,54 +68,51 @@ Ví dụ: Các trình duyệt hiện đại cho phép JavaScript làm việc với các tệp, nhưng quyền truy cập bị hạn chế và chỉ được cung cấp nếu người dùng thực hiện các hành động nhất định, như kéo-thả (dropping) một file vào cửa sổ trình duyệt hoặc chọn file qua thẻ ``. Có nhiều cách để tương tác với webcam/ camera/ micro và các thiết bị khác nhưng chúng cần có sự cho phép rõ ràng của người dùng. Vì vậy, một trang Web kích hoạt JavaScript không thể lén kích hoạt webcam, ghi hình và gửi thông tin cho [NSA](https://en.wikipedia.org/wiki/National_Security_Agency). -- Các tabs/windows không nhận biết lẫn nhau. Kể cả trong trường hợp từ Tab này bạn chạy JavaScript mở ra một tab khác. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port). +- Các tabs/windows không nhận biết lẫn nhau. Kể cả trong trường hợp từ Tab này bạn chạy JavaScript mở ra một tab khác, cũng không thể nếu mở các trang web khác nhai (khác địa chỉ, protocol hoặc port). - This is called the "Same Origin Policy". To work around that, *both pages* must contain a special JavaScript code that handles data exchange. + Để có thể trao đổi dữ liệu giữa hai tab với nhau thì 2 trang web mở trên 2 tab này phải có các đoạn script đặc biệt để trao đổi dữ liệu qua lại. - The limitation is again for user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com` and steal information from there. -- JavaScript can easily communicate over the net to the server where the current page came from. But its ability to receive data from other sites/domains is crippled. Though possible, it requires explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's safety limitations. + Sự giới hạn này đảm bảo an toàn cho người dùng. Ví dụ bạn mở trang web `http://anysite.com` ở một tab và vào `http://gmail.com` ở tab khác. Sẽ ko thể đọc trộm gmail được. +- JavaScript có thể dễ dàng truyền tải dữ liệu với máy chủ Web đang mở. Còn khả năng nhận dữ liệu từ các trang web / tên miền khác bị chặn. Nếu muốn mở, đòi hỏi sự đồng ý rõ ràng (thể hiện trong tiêu đề HTTP) từ phía xa. Một lần nữa, đó là những hạn chế về an toàn và bảo mật. ![](limitations.png) -Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow installing plugin/extensions which may get extended permissions. +Các giới hạn đó không tồn tại nếu JavaScript được sử dụng bên ngoài trình duyệt, ví dụ trên máy chủ. Các trình duyệt hiện đại cũng cho phép cài đặt plugin / tiện ích mở rộng có thể nhận được giấy phép mở rộng. -## What makes JavaScript unique? +## Điều gì làm cho JavaScript trở nên độc nhất vô nhị? -There are at least *three* great things about JavaScript: +Có ít nhất ba điều sau: ```compare -+ Full integration with HTML/CSS. -+ Simple things done simply. -+ Supported by all major browsers and enabled by default. ++ Tích hợp hoàn toàn với HTML/CSS. ++ Những việc đơn giản được thực hiện một cách đơn giản. ++ Được hỗ trợ bởi hầu hết các trình duyệt ở cấu hình mặc định. ``` +Ba điều này chỉ tồn tại trong JavaScript mà không phải là một công nghệ nào khác trên trình duyệt.. -Combined, these three things exist only in JavaScript and no other browser technology. +Điều này làm cho JavaScript trở nên độc nhất vô nhị. Và đó là lý do tại sao JavaScript là công cụ phổ biến nhất để tạo các giao diện trình duyệt web. -That's what makes JavaScript unique. That's why it's the most widespread tool to create browser interfaces. +Khi lên kế hoạch học tập một công nghệ mới, điều này có lợi cho việc kiểm tra nhu cầu sử dụng, đặc điểm công nghệ. Vì vậy để bắt kịp với thế giới, hãy chuyển sang các xu hướng hiện đại nhất bao gồm đặc tả mới (như ES6, ES7...) và khả năng tương thích trình duyệt hiện tại cũng như tương lai. -While planning to learn a new technology, it's beneficial to check its perspectives. So let's move on to the modern trends that include new languages and browser abilities. +## Các ngôn ngữ dựa trên JavaScript -## Languages "over" JavaScript +Cú pháp của JavaScript không phải luôn phù hợp với nhu cầu của mọi người. Vì mỗi người lại muốn có những tính năng khác nhau, làm các dự án khác nhau. -The syntax of JavaScript does not suit everyone's needs. Different people want different features. +Gần đây có rất nhiều ngôn ngữ mới xuất hiện, code của chúng được được chuyển đổi sang JavaScript trước khi chạy trong trình duyệt. -That's to be expected, because projects and requirements are different for everyone. +Các công cụ hiện đại làm cho quá trình chuyển đổi tự động và rất nhanh, thực sự cho phép các nhà phát triển code mã bằng một ngôn ngữ khác và nó sẽ được hệ thống dịch sang JavaScript tự động hoàn toàn. -So recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run in the browser. +Ví dụ về các ngôn ngữ này: -Modern tools make the transpilation very fast and transparent, actually allowing developers to code in another language and autoconverting it "under the hood". +- [CoffeeScript](http://coffeescript.org/) cú pháp tương tự JavaScript nhưng ngắn hơn, cho phép để viết code chính xác hơn và rõ ràng. Giống như Rub vậy. +- [TypeScript](http://www.typescriptlang.org/) tập trung vào việc "gõ dữ liệu một cách chặt chẽ", để đơn giản hóa sự phát triển và hỗ trợ của các hệ thống phức tạp. Nó được phát triển bởi Microsoft. +- [Dart](https://www.dartlang.org/) là một ngôn ngữ độc lập có Engine riêng chạy ở môi trường không phải trình duyệt (như ứng dụng dành cho thiết bị di động). Nó ban đầu được cung cấp bởi Google như là một sự thay thế cho JavaScript, nhưng đến nay, các trình duyệt yêu cầu nó chuyển đổi sang JavaScript trước khi chạy. -Examples of such languages: +Còn có nhiều nữa. Tất nhiên ngay cả khi chúng ta sử dụng một trong những ngôn ngữ đó, chúng ta cũng nên biết JavaScript, để thực sự hiểu những gì chúng ta đang làm. -- [CoffeeScript](http://coffeescript.org/) is a "syntax sugar" for JavaScript, it introduces shorter syntax, allowing to write more precise and clear code. Usually Ruby devs like it. -- [TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing", to simplify development and support of complex systems. It is developed by Microsoft. -- [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps). It was initially offered by Google as a replacement for JavaScript, but as of now, browsers require it to be transpiled to JavaScript just like the ones above. +## Tóm tắt lại -There are more. Of course even if we use one of those languages, we should also know JavaScript, to really understand what we're doing. - -## Summary - -- JavaScript was initially created as a browser-only language, but now it is used in many other environments as well. -- At this moment, JavaScript has a unique position as the most widely-adopted browser language with full integration with HTML/CSS. -- There are many languages that get "transpiled" to JavaScript and provide certain features. It is recommended to take a look at them, at least briefly, after mastering JavaScript. +- JavaScript ban đầu được tạo ra như là một ngôn ngữ duy nhất của trình duyệt, nhưng bây giờ nó được sử dụng trong nhiều môi trường khác nữa. +- Tại thời điểm này, JavaScript là ngôn ngữ duy nhất, phổ biến nhất mà các trình duyệt đều sử dụng và tích hợp hoàn toàn với HTML / CSS. +- Có nhiều ngôn ngữ được chuyển tải từ JavaScript và cung cấp một số tính năng nhất định. Chúng tôi khuyên bạn nên xem xét chúng, ít nhất một thời gian ngắn, sau khi đã pro JavaScript rồi. From 30a4d300c817897193a954ccbda1b386cce90de5 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 15:38:28 +0700 Subject: [PATCH 06/78] Vn Vn --- .../2-code-editors/article.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/1-js/01-getting-started/2-code-editors/article.md b/1-js/01-getting-started/2-code-editors/article.md index 65ef7476e3..22b7b28f8b 100644 --- a/1-js/01-getting-started/2-code-editors/article.md +++ b/1-js/01-getting-started/2-code-editors/article.md @@ -1,28 +1,28 @@ -# Code editors +# Trình biên soạn - Code editors -A code editor is the place where a programmer spends most of his time. +Là nơi chiếm nhiều thời gian nhất của lập trình viên. Với một dự án lớn, nhiều file nhiều ngôn ngữ, cần tích hợp đủ thứ, cần chạy thử, debug, kiểm tra lỗi chính tả....tất nhiên là bạn không thể làm tay, mở từng file, kiểm tra từng code được rồi đúng không. Rất tốn thời gian và công sức. Vì vậy cần Coder Editor. -There are two archetypes: IDE and lightweight editors. Many people feel comfortable choosing one tool of each type. +Có 2 loại chính: IDE và lightweight editors. Ai thích dùng loại nào thì dùng. [cut] ## IDE -The term [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) (Integrated Development Environment) means a powerful editor with many features that usually operates on a "whole project". As said, that's not just an editor, but a full-scale "development environment". +Thuật ngữ [IDE] (https://en.wikipedia.org/wiki/Integrated_development_environment) (Môi trường phát triển tích hợp) có nghĩa là một trình soạn thảo mạnh mẽ với nhiều tính năng thường hoạt động trên "toàn bộ dự án". Như đã nói, đó không chỉ là một biên tập viên, mà còn là một "môi trường phát triển" đầy đủ. -An IDE loads the project (can be many files), and then allows navigation between files, provides autocompletion based on the whole project, integrates with a version management system (like [git](https://git-scm.com/)), a testing environment and other "project-level" stuff. +IDE tải dự án (có thể là nhiều tệp, file), và sau đó cho phép điều hướng giữa các tệp tin, cung cấp tự động hoàn thành dựa trên toàn bộ dự án, tích hợp với hệ thống quản lý phiên bản (như [git] (https://git-scm.com/) ), một môi trường thử nghiệm và công cụ khác. -If you haven't considered selecting an IDE yet, look at the following variants: +Có thể tham khảo một số IDE bên dưới: -- IntelliJ editors: [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development and [PHPStorm (PHP)](http://www.jetbrains.com/phpstorm/), [IDEA (Java)](http://www.jetbrains.com/idea/), [RubyMine (Ruby)](http://www.jetbrains.com/ruby/) and others if you need additional languages. -- Visual Studio is fine if you're a .NET developer, and a free version is available ([Visual Studio Community](https://www.visualstudio.com/vs/community/)) -- Eclipse-based products, like [Aptana](http://www.aptana.com/) and Zend Studio. -- [Komodo IDE](http://www.activestate.com/komodo-ide) and its lightweight free version [Komodo Edit](http://www.activestate.com/komodo-edit). +- IntelliJ editors: [WebStorm](http://www.jetbrains.com/webstorm/) cho phát triển frontend và [PHPStorm (PHP)](http://www.jetbrains.com/phpstorm/), [IDEA (Java)](http://www.jetbrains.com/idea/), [RubyMine (Ruby)](http://www.jetbrains.com/ruby/) nếu muốn dùng thêm các ngôn ngữ khác. +- Visual Studio nếu bạn là lập trình viên .NET, bản này miễn phí nhé ([Visual Studio Community](https://www.visualstudio.com/vs/community/)) +- Bộ IDE của Eclipse, như [Aptana](http://www.aptana.com/) và Zend Studio. +- [Komodo IDE](http://www.activestate.com/komodo-ide) nhẹ và miễn phí [Komodo Edit](http://www.activestate.com/komodo-edit). - [Netbeans](http://netbeans.org/). -All of the IDEs listed above are available on both Windows and Mac, and the IDEs other than Visual Studio are also available on Linux. +Tất cả các IDE được liệt kê ở trên dùng được trên Windows và Mac và các IDE khác ngoài ra Visual Studio dùng được trên Linux. -Most IDEs are paid, but have a trial period. Their cost is usually negligible compared to a qualified developer's salary, so just choose the best one for you. +Hầu hết các IDE đều phải trả phí, nhưng có cho thời gian dùng thử. Chi phí của họ thường không đáng kể so với mức lương của nhà phát triển đủ điều kiện, vì vậy chỉ cần chọn mức giá tốt nhất cho bạn. (Lừa đó, mắc lòi ra :D) ## Lightweight editors From 2705db532b693847ecd728529107faa2f1ed4470 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 16:11:18 +0700 Subject: [PATCH 07/78] VN VN --- .../2-code-editors/article.md | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/1-js/01-getting-started/2-code-editors/article.md b/1-js/01-getting-started/2-code-editors/article.md index 22b7b28f8b..ab5de4593c 100644 --- a/1-js/01-getting-started/2-code-editors/article.md +++ b/1-js/01-getting-started/2-code-editors/article.md @@ -24,39 +24,38 @@ Tất cả các IDE được liệt kê ở trên dùng được trên Windows v Hầu hết các IDE đều phải trả phí, nhưng có cho thời gian dùng thử. Chi phí của họ thường không đáng kể so với mức lương của nhà phát triển đủ điều kiện, vì vậy chỉ cần chọn mức giá tốt nhất cho bạn. (Lừa đó, mắc lòi ra :D) -## Lightweight editors +## Lightweight editors - trình biên tập nhẹ -"Lightweight editors" are not as powerful as IDEs, but they're fast, elegant and simple. +"Lightweight editors" không mạnh mẽ như IDE, nhưng mà nó nhẹ, nhanh và đơn giản. -They are mainly used to instantly open and edit a file. +Chủ yếu dùng để mở và chỉnh sửa file. -The main difference between a "lightweight editor" and an "IDE" is that an IDE works on a project-level, so it loads much more data on start, analyzes the project structure if needed and so on. A lightweight editor is much faster if we need only one file. +Sự khác biệt chính giữa "Lightweight editors" và "IDE" là một IDE hoạt động ở cấp độ dự án, vì vậy nó sẽ tải nhiều dữ liệu hơn khi bắt đầu, phân tích cấu trúc dự án nếu cần thiết. Lightweight editors nhanh hơn nhiều vì load tệp riêng lẽ. +Trong thực tế, các Lightweight editors có thể có rất nhiều plugin bao gồm cả phân tích cú pháp, tự động hoàn thành lệnh, vì vậy không có ranh giới rõ ràng giữa Lightweight editors và IDE. -In practice, lightweight editors may have a lot of plugins including directory-level syntax analyzers and autocompleters, so there's no strict border between a lightweight editor and an IDE. - -The following options deserve your attention: +Một số Lightweight editors đáng được chú ý: - [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free). - [Atom](https://atom.io/) (cross-platform, free). - [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware). - [Notepad++](https://notepad-plus-plus.org/) (Windows, free). -- Vim and Emacs are also cool, if you know how to use them. +- Vim và Emacs cũng tàm tạm, nếu bạn quen với style của Linux -## My favorites +## Tác giả dùng cái gì ? -The personal preference of the author is to have both an IDE for projects and a lightweight editor for quick and easy file editing. +Sở thích cá nhân của tác giả là có cả một IDE cho các dự án và một trình soạn thảo nhẹ để chỉnh sửa tập tin nhanh chóng và dễ dàng. -I'm using: +Tôi dùng: -- [WebStorm](http://www.jetbrains.com/webstorm/) for JS, and if there is one more language in the project, then I switch to other Jetbrains editors like [PHPStorm](http://www.jetbrains.com/phpstorm/) (PHP), [IDEA](http://www.jetbrains.com/idea/) (Java), [RubyMine](http://www.jetbrains.com/ruby/) (Ruby). There are editors for other languages too, but I haven't used them. -- As a lightweight editor -- [Sublime Text](http://www.sublimetext.com) or [Atom](https://atom.io/). +- [WebStorm](http://www.jetbrains.com/webstorm/) cho JS, và nếu trong dự án có cả ngôn ngữ khác nữa thì tôi dùng thêm các sản phẩm của Jetbrains như [PHPStorm](http://www.jetbrains.com/phpstorm/) (PHP), [IDEA](http://www.jetbrains.com/idea/) (Java), [RubyMine](http://www.jetbrains.com/ruby/) (Ruby). +- lightweight editor -- tôi dùng [Sublime Text](http://www.sublimetext.com) hoặc [Atom](https://atom.io/). -If you don't know what to choose, you can consider these ones. +Nếu bạn không biết chọn gì, thì chọn đại Atom đi :D. -## Let's not argue +## Đừng tranh luận chọn dùng Editor nào nhé -The editors in the lists above are those that either I or my friends who I consider good developers have been using for a long time and are happy with. +Các Code Editor trong danh sách ở trên là được tôi hoặc bạn bè của tôi cho rằng các nhà phát triển giỏi đã và đang sử dụng trong một thời gian dài và họ khuyến khích người khác sử dụng. -There are other great editors in our big world. Please choose the one you like the most. +Có nhiều Editor vĩ đại khác trong thế giới lập trình rộng lớn của chúng ta. Vui lòng chọn một trong những bạn thích nhất. -The choice of an editor, like any other tool, is individual and depends on your projects, habits, personal preferences. +Việc lựa chọn một trình soạn thảo, giống như bất kỳ công cụ nào khác, là một việc cá nhân và phụ thuộc vào các dự án, thói quen, sở thích cá nhân của bạn. From 509fcb2463c9d0b94cafbf1632c7cd8874034211 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 16:41:26 +0700 Subject: [PATCH 08/78] ds sad --- 1-js/01-getting-started/3-devtools/article.md | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/1-js/01-getting-started/3-devtools/article.md b/1-js/01-getting-started/3-devtools/article.md index 34e5c9a75b..9fedf5cd4e 100644 --- a/1-js/01-getting-started/3-devtools/article.md +++ b/1-js/01-getting-started/3-devtools/article.md @@ -1,60 +1,57 @@ # Developer console -Code is prone to errors. You are quite likely to make errors... Oh, what am I talking about? You are *absolutely* going to make errors, at least if you're a human, not a [robot](https://en.wikipedia.org/wiki/Bender_(Futurama)). +Code thì thường hay có lỗi. Có thể sai lỗi chính tả, thiếu code, không hỗ trợ chức năng....và khi lỗi thường sẽ có thông báo là lỗi gì trên màn hình console. -But in the browser, a user doesn't see the errors by default. So, if something goes wrong in the script, we won't see what's broken and can't fix it. +Tuy nhiên trên trình duyệt thì sẽ không thấy được các thông báo lỗi này để mà từ đó chúng ta có được thông tin và đi tìm xem đang lỗi chỗ nào. Vậy phải làm sao đây ? -To see errors and get a lot of other useful information about scripts, browsers have embedded "developer tools". +Để xem các thông tin lỗi này trên trình duyệt có nhúng sẵn chức năng gọi là "công cụ cho nhà phát triển" "developer tools". -Most often developers lean towards Chrome or Firefox for development, because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most people have a "favorite" browser and switch to others if a problem is browser-specific. +Các lập trình viên thường chọn Developer Tool trên Chrome hoặc FireFox. Vì 2 thằng này pro nhất so với tất cả Developer tool khác. -Developer tools are really powerful, there are many features. To start, we'll learn how to open them, look at errors and run JavaScript commands. +Developer tools thực sự mạnh mẽ và có nhiều chức năng. Chúng ta sẽ học cách sử dụng Developer Tool bên dưới. [cut] ## Google Chrome -Open the page [bug.html](bug.html). +Mở trang này lên [bug.html](bug.html). Yên tâm, méo có Virus đâu -There's an error in the JavaScript code on it. It's hidden from a regular visitor's eyes, so let's open developer tools to see it. +Có lỗi xảy ra trên trang này tuy nhiên chúng ta chẳng thấy được. Giờ mở Developer Tool lên xem nào. -Press `key:F12` or, if you're on Mac, then `key:Cmd+Opt+J`. +Nhấn `key:F12` hoặc chuột phải và chọn `inspect`. -The developer tools will open on the Console tab by default. - -It looks somewhat like this: +Nhìn nó sẽ như này: ![chrome](chrome.png) -The exact look of developer tools depends on your version of Chrome. It changes from time to time, but should be similar. - -- Here we can see the red-colored error message. In this case the script contains an unknown "lalala" command. -- On the right, there is a clickable link to the source `bug.html:12` with the line number where the error has occurred. +Ở tab console sẽ thấy nó thông báo lỗi. -Below the error message there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands and press `key:Enter` to run them (`key:Shift+Enter` to input multi-line commands). +- Cái dòng thông báo màu đỏ đó chính là 1 cái lỗi. Nó nói là "lalala" không được định nghĩa. +- Tiếp, click vào cái link màu xanh `bug.html:12` 12 ở đây là dòng code đang lỗi. -Now we can see errors and that's enough for the start. We'll be back to developer tools later and cover debugging more in-depth in the chapter . +Bên dưới thông báo lỗi là dấu nhắc lệnh màu xanh `>` . Gõ các câu lệnh JavaScript vào đây và nhấn `key:Enter` để chạy (`key:Shift+Enter` để nhập nhiều dòng lệnh). +Ok thấy lỗi rồi thì quay lại Code Editor và sửa lại dòng code số 12 trong file bug.html đi. +Sau này sẽ tìm hiểu sâu hơn về debug trên Chrome tại . -## Firefox, Edge and others -Most other browsers use `key:F12` to open developer tools. +## Firefox, Edge và những thằng khác -The look & feel of them is quite similar. Once you know how to use one of them (you can start with Chrome), you can easily switch to another. +Nói chung là tương tự thôi, có thể nhìn giao diện nó hơi khác chút. ## Safari -Safari (Mac browser, not supported by Windows/Linux) is a little bit special here. We need to enable the "Develop menu" first. +Safari (Trình duyệt của máy MAC) thì hơi khác chút. Cần mở chức năng "Develop menu" trước. -Open Preferences and go to "Advanced" pane. There's a checkbox at the bottom: +Mở Preferences --> "Advanced" Đánh dấu vào cái checkbox như hình: ![safari](safari.png) -Now `key:Cmd+Opt+C` can toggle the console. Also note that the new top menu item named "Develop" has appeared. It has many commands and options. +Nhấn `key:Cmd+Opt+C` để mở Developer Tool nhé. Thân ái. -## Summary +## Tóm tắt -- Developer tools allow us to see errors, run commands, examine variables and much more. -- They can be opened with `key:F12` for most browsers under Windows. Chrome for Mac needs `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (need to enable first). +- Developer tools giúp chúng ta thấy được lỗi, chạy lệnh và nhiều chức năng khác. +- Mở Developer tool bằng cách nhấn `key:F12` đối với đa số trình duyệt trên Windows. Chrome cho Mac nhấn `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (nhớ mở chức năng này lên đã). -Now we have the environment ready. In the next section we'll get down to JavaScript. +Bây giờ chúng ta đã có công cụ và môi trường sẵn sàng để học tập. Trong phần kế tiếp, chúng ta sẽ đến với JavaScript. From 96703810519be949be108e4052f9ceb2ae53f272 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 20:45:51 +0700 Subject: [PATCH 09/78] vn vn --- 1-js/02-first-steps/01-hello-world/article.md | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/1-js/02-first-steps/01-hello-world/article.md b/1-js/02-first-steps/01-hello-world/article.md index e69a25f0c6..df475ef35e 100644 --- a/1-js/02-first-steps/01-hello-world/article.md +++ b/1-js/02-first-steps/01-hello-world/article.md @@ -1,19 +1,19 @@ # Hello, world! -The tutorial that you're reading is about core JavaScript, which is platform-independent. Further on, you will learn Node.JS and other platforms that use it. +Hướng dẫn mà bạn đang đọc là cơ bản cốt lõi của JavaScript, dùng được trên mọi nền tảng. Thêm nữa, bạn sẽ học về Node.JS và các nền tảng khác sử dụng JavaScript. -But, we need a working environment to run our scripts, and, just because this book is online, the browser is a good choice. We'll keep the amount of browser-specific commands (like `alert`) to a minimum, so that you don't spend time on them if you plan to concentrate on another environment like Node.JS. On the other hand, browser details are explained in detail in the [next part](/ui) of the tutorial. +Chúng ta sẽ học và thực hành các đoạn mã JavaScript ngay trên trình duyệt. Tuy nhiên chúng ta sẽ dùng các câu lênh đặc trưng của trình duyệt (như `alert`) ở mức tối thiểu, do đó nên bạn không cần mất thời gian đi tìm hiểu sâu về các câu lệnh như thế này, thay vì đó hãy tập trung vào một môi trường khác như Node.JS. Các câu lệnh đặc trưng và chi tiết của trình duyệt sẽ được giải thích trong phần [tiếp theo] (/ ui) của hướng dẫn này. -So first, let's see how to attach a script to a webpage. For server-side environments, you can just execute it with a command like `"node my.js"` for Node.JS. +Đầu tiên, hãy xem cách để nhúng một đoạn mã JavaScript vào một trang web. Đối với các môi trường phía máy chủ như Node.JS, bạn chỉ có thể thực hiện nó bằng cửa sổ lệnh ví dụ như `" node my.js "`. [cut] -## The "script" tag +## Thẻ "script" -JavaScript programs can be inserted in any part of an HTML document with the help of the ` ``` - These comments were supposed to hide the code from an old browser that didn't know about a ` + ``` -Here `/path/to/script.js` is an absolute path to the file with the script (from the site root). +Ở đây `/đường/dẫn/đến/file/script.js` là đường dẫn tuyệt đối đến file script.js (tính từ site root). -It is also possible to provide a path relative to the current page. For instance, `src="script.js"` would mean a file `"script.js"` in the current folder. +Cũng có thể dùng đường dẫn tương đối, ví dụ `src="script.js"` nghĩa là `"script.js"` nằm trong thư mục hiện hành. -We can give a full URL as well, for instance: +Cũng có thể điền URL đầy đủ đến Script nếu nó được lưu Online ở đâu đó trên mạng: ```html ``` -To attach several scripts, use multiple tags: +Add nhiều file thì dùng nhiều thẻ như bên dưới: ```html @@ -95,29 +95,29 @@ To attach several scripts, use multiple tags: ``` ```smart -As a rule, only the simplest scripts are put into HTML. More complex ones reside in separate files. +Theo nguyên tắc, chỉ có các tập lệnh đơn giản nhất được đưa vào tài liệu HTML. Những tệp tin phức tạp hơn nằm trong các tệp riêng biệt. -The benefit of a separate file is that the browser will download it and then store in its [cache](https://en.wikipedia.org/wiki/Web_cache). +Lợi ích của việc tách code ra riêng biệt các file là trình duyệt sẽ tải xuống và sau đó lưu trữ trong [cache](https://en.wikipedia.org/wiki/Web_cache). -After this, other pages that want the same script will take it from the cache instead of downloading it. So the file is actually downloaded only once. +Sau đó nếu tải lại trang web thì sẽ rất nhanh vì không cần tải các script nữa, nó lưu trong cache rồi. -That saves traffic and makes pages faster. +Điều này sẽ tiết kiệm băng thông và làm trang web chạy nhanh hơn. ``` -````warn header="If `src` is set, the script content is ignored." -A single ` ``` -We must choose: either it's an external ` @@ -127,11 +127,11 @@ The example above can be split into two scripts to work: ``` ```` -## Summary +## Tổng kết -- We can use a ``. +- Chúng ta sử dụng thẻ ``. -There is much more to learn about browser scripts and their interaction with the web-page. But let's keep in mind that this part of the tutorial is devoted to the JavaScript language, so we shouldn't distract ourselves from it. We'll be using a browser as a way to run JavaScript, which is very convenient for online reading, but yet one of many. +Có rất nhiều thứ để tìm hiểu về các kịch bản của trình duyệt và sự tương tác của chúng với trang web. Nhưng chúng ta hãy nhớ rằng phần này của hướng dẫn này dành cho ngôn ngữ JavaScript, hãy tập trung vào JS. Chúng tôi sẽ sử dụng một trình duyệt như một cách để chạy JavaScript, để tiện hơn cho việc học trực tuyến. From 27310fec80241d054d8abca5f9ba092cd3eafdfc Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 21:22:49 +0700 Subject: [PATCH 10/78] dsf adsf --- 1-js/02-first-steps/02-structure/article.md | 98 ++++++++++----------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/1-js/02-first-steps/02-structure/article.md b/1-js/02-first-steps/02-structure/article.md index fc1dc46e70..6f3ab3c20b 100644 --- a/1-js/02-first-steps/02-structure/article.md +++ b/1-js/02-first-steps/02-structure/article.md @@ -1,46 +1,46 @@ -# Code structure +# Cấu trúc code -The first thing to study is the building blocks of the code. +Đầu tiên chúng ta sẽ học về các khối lệnh. [cut] -## Statements +## Câu lệnh -Statements are syntax constructs and commands that perform actions. +Câu lệnh (Statements) là cấu trúc ngữ pháp và lệnh để thực hiện một hành động. -We've already seen a statement `alert('Hello, world!')`, which shows the message. +Chúng ta đã được thấy câu lệnh `alert('Hello, world!')`, để show ra một câu chào lên màn hình rồi. -We can have as many statements in the code as we want. Another statement can be separated with a semicolon. +Một chương trình thường sẽ có nhiều câu lệnh và chúng thường được tách biệt nhau bởi dấu chấm phẩy. -For example, here we split the message into two: +Ví dụ: ```js run no-beautify alert('Hello'); alert('World'); ``` -Usually each statement is written on a separate line -- thus the code becomes more readable: +Thông thường mỗi câu lệnh nên viết trên một dòng cho dễ đọc: ```js run no-beautify alert('Hello'); alert('World'); ``` -## Semicolons [#semicolon] +## Dấu chấm phấy (Semicolons [#semicolon]) -A semicolon may be omitted in most cases when a line break exists. +Có thể bõ qua dấu chấm phẩy nếu xuống hàng. -This would also work: +Như thế này: ```js run no-beautify alert('Hello') alert('World') ``` -Here JavaScript interprets the line break as an "implicit" semicolon. That's also called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion). +Đây được gọi là dấu chấm phẩy không tường minh, xem thêm tại đây [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion). -**In most cases a newline implies a semicolon. But "in most cases" does not mean "always"!** +**Trong nhiều trường hợp xuống dòng có thể thay thế cho dấu chấm phẩy nhưng "KHÔNG PHẢI LUÔN LUÔN ĐÚNG"!** -There are cases when a newline does not mean a semicolon, for example: +Ví dụ: ```js run no-beautify alert(3 + @@ -48,22 +48,22 @@ alert(3 + + 2); ``` -The code outputs `6`, because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", no semicolon required. And in this case that works as intended. +kết quả output là `6`, Vì JavaScript không tự chèn dấu chấm phẩy nếu kết thúc dòng là `"+"`. -**But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.** +**Nhưng có những tình huống mà JavaScript sai lầm khi chèn dấu chấm phẩy.** -Errors which occur in such cases are quite hard to find and fix. +Lỗi xảy ra trong những trường hợp này khá khó tìm và khắc phục. ````smart header="An example of an error" -If you're curious to see a concrete example of such an error, check this code out: +Nếu bạn tò mò thì xem ví dụ dưới đây: ```js run [1, 2].forEach(alert) ``` -No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later, for now it does not matter. Let's just remember the result: it shows `1`, then `2`. +Nếu không biết các ký tự `[]` và hàm `forEach` thì chúng ta sẽ học sau, không cần mất công tìm hiểu. Bạn chỉ cần biết đoạn mã trên sẽ thông báo ra màn hình `1`, và sau đó là `2`. -Now let's add an `alert` before the code and *not* finish it with a semicolon: +Bây giờ thêm câu lệnh `alert` đằng trước và *KHÔNG* dùng dấu chấm phẩy để kết thúc câu lệnh này: ```js run no-beautify alert("There will be an error") @@ -71,80 +71,78 @@ alert("There will be an error") [1, 2].forEach(alert) ``` -Now if we run it, only the first `alert` is shown, and then we have an error! +Nếu chạy bạn sẽ thấy lệnh `alert` sẽ show ra màn hình, sau đó thì sẽ có thông báo lỗi. -But everything is fine again if we add a semicolon after `alert`: +Ok giờ ta sẽ sửa bằng cách thêm dấu chấm phẩy sau lệnh `alert`: ```js run alert("All fine now"); [1, 2].forEach(alert) ``` -Now we have the "All fine now" message and then `1` and `2`. +Giờ sẽ thấy thông báo "All fine now" sau đó là `1` và `2`. -The error in the no-semicolon variant occurs because JavaScript does not imply a semicolon before square brackets `[...]`. +Lỗi xảy ra do JavaScript ngụ ý là không chèn dấu chấm phẩy trước cặp ngoặc vuông `[...]`. -So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. That's how the engine sees it: +Vì vậy code được engine nhìn thấy như một câu lệnh đơn như thế này: ```js run no-beautify alert("There will be an error")[1, 2].forEach(alert) ``` -But it should be two separate statements, not a single one. Such a merging in this case is just wrong, hence the error. There are other situations when such a thing happens. +Và lỗi xảy ra. ```` -It's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them. +Bạn nên đặt dấu chấm phẩy giữa các câu lệnh ngay cả khi chúng được phân cách bằng dòng mới. Quy tắc này được cộng đồng chấp nhận rộng rãi. Chúng ta hãy lưu ý một lần nữa - * có thể * bỏ dấu chấm phẩy trong hầu hết trường hợp. Nhưng để an toàn hơn - đặc biệt là cho người mới bắt đầu - hãy sử dụng dấu chấm phẩy. -## Comments +## Ghi chú -As time goes on, the program becomes more and more complex. It becomes necessary to add *comments* which describe what happens and why. +Theo thời gian, chương trình sẽ mở rộng và phức tạp hơn. Việc thêm các ghi chú và mô tả vào để người đọc có thể gợi nhớ những ý nghĩa nào đó là cần thiết. VD bạn code xong để một thời gian dài không sử dụng, sau này đọc lại thì chả hiểu chương trình mình đã viết nó chạy như nào và làm gì. Nếu có ghi chú trước đó thì khỏe rồi, đọc phát là nhớ lại ngay. -Comments can be put into any place of the script. They don't affect the execution, because the engine simply ignores them. +Ghi chú có thể viết ở bất kỳ đâu trong chương trình, Engine sẽ bõ qua chúng. -**One-line comments start with the two forward slash characters `//`.** +**Ghi chú một dòng thì dùng 2 dấu gạch chéo như này `//`.** -The rest of the line is a comment. It may occupy a full line of its own or follow a statement. - -Like here: +Ví dụ: ```js run -// This comment occupies a line of its own +// Đây là một ghi chú alert('Hello'); -alert('World'); // This comment follows the statement +alert('World'); // Câu lệnh này để thông báo bla bla... ``` -**Multiline comments start with a forward slash and an asterisk /* and end with an asterisk and a forward slash */.** +**Ghi chú trên nhiều dòng bắt đầu bằng /* và kết thúc bằng */.** -Like this: +Như thế này: ```js run -/* An example with two messages. -This is a multiline comment. +/* Đây là ví dụ. +Về việc ghi chú trên nhiều dòng. */ alert('Hello'); alert('World'); ``` -The content of comments is ignored, so if we put code inside /* ... */ it won't execute. +Nội dung ghi chú giữa hai cặp /* ... */ sẽ được engine bõ qua. -Sometimes it comes in handy to temporarily disable a part of code: +Đôi khi nó được dùng để vô hiệu hóa một đoạn code: ```js run -/* Commenting out the code +/* ghi chú dòng code này alert('Hello'); */ alert('World'); ``` ```smart header="Use hotkeys!" -In most editors a line of code can be commented out by `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac try `key:Cmd` instead of `key:Ctrl`. +Hầu hết các Editor sử dụng phím tắt `key:Ctrl+/` cho ghi chú một dòng và `key:Ctrl+Shift+/` -- cho ghi chú nhiều dòng (nhớ bôi đen một đoạn code nào đó trước). Đối với MAC dùng phím `key:Cmd` thay cho `key:Ctrl`. ``` -````warn header="Nested comments are not supported!" -There may not be `/*...*/` inside another `/*...*/`. +````warn header="Ghi chú chồng nhau không được hỗ trợ!" +Ghi chú `/*...*/` phía trong ghi chú khác `/*...*/`. -Such code will die with an error: +sẽ làm code báo lỗi ngay: ```js run no-beautify /* @@ -154,8 +152,8 @@ alert( 'World' ); ``` ```` -Please, don't hesitate to comment your code. +Xin vui lòng, đừng ngần ngại ghi chú code của bạn. -Comments increase the overall code footprint, but that's not a problem at all. There are many tools which minify the code before publishing to the production server. They remove comments, so they don't appear in the working scripts. Therefore comments do not have any negative effects on production at all. +Ghi chú làm tăng độ dài code, nhưng đó không phải là vấn đề. Có rất nhiều công cụ giảm thiểu mã trước khi public lên máy chủ. Chúng sẽ xóa ghi chú, vì vậy ghi chú sẽ không xuất hiện trong các tập lệnh làm việc. Cho nên việc ghi chú sẽ không có tác động tiêu cực nào. -Further in the tutorial, there will be a chapter that also explains how to write better comments. +Trong bài tiếp theo chúng ta sẽ học cách viết ghi chú sao cho chuẩn và đẹp. From 32b0620ed0bf1c361ff1a488632fdc0728f0f6a6 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 22:08:32 +0700 Subject: [PATCH 11/78] dfa fds --- 1-js/02-first-steps/03-strict-mode/article.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/1-js/02-first-steps/03-strict-mode/article.md b/1-js/02-first-steps/03-strict-mode/article.md index a7bb414b25..1d74559e27 100644 --- a/1-js/02-first-steps/03-strict-mode/article.md +++ b/1-js/02-first-steps/03-strict-mode/article.md @@ -1,18 +1,18 @@ -# The modern mode, "use strict" +# Chế độ hiện đại Strict mode, "use strict" -For a long time JavaScript was evolving without compatibility issues. New features were added to the language, but the old functionality did not change. +Trong một thời gian dài JavaScript đã được phát triển mà không có vấn đề gì về tương thích. Các tính năng mới được thêm vào ngôn ngữ, đồng thời chức năng cũ không thay đổi. -That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript creators got stuck in the language forever. +Điều này có lợi ích là không bao giờ phá vỡ mã nguồn hiện có. Nhưng nhược điểm là bất kỳ sai lầm hoặc một quyết định không hoàn hảo nào đó se bị mắc kẹt trong ngôn ngữ mãi mãi. -It had been so until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and modified some of the existing ones. To keep the old code working, most modifications are off by default. One needs to enable them explicitly with a special directive `"use strict"`. +Cho đến năm 2009 khi ECMAScript 5 (ES5) ra đời. Nó bổ sung các tính năng mới cho ngôn ngữ và sửa đổi một số các tính năng hiện có. Để giữ mã cũ có thể làm việc, hầu hết các sửa đổi được tắt theo mặc định. Một nhu cầu cho phép enable các thay đổi này với một chỉ thị đặc biệt là dùng `"use strict"`- hay sử dụng nghiêm ngặt [cut] ## "use strict" -The directive looks like a string: `"use strict"` or `'use strict'`. When it is located on the top of the script, then the whole script works the "modern" way. +Chỉ thị này nhìn có vẻ giống một chuỗi ký tự: `"use strict"` hoặc `'use strict'`. Khi sử dụng chế độ này bằng cách đặt chỉ thị này vào đầu script của bạn, nó có ý nghĩa là code sẽ được chạy theo cách hiện đại. -For example +Ví dụ: ```js "use strict"; @@ -21,15 +21,15 @@ For example ... ``` -We will learn functions (a way to group commands) soon. +Chúng ta sẽ học về hàm (một cách để nhóm các câu lệnh) sớm thôi. -Looking ahead let's just note that `"use strict"` can be put at the start of a function (most kinds of functions) instead of the whole script. Then strict mode is enabled in that function only. But usually people use it for the whole script. +Nhìn code phía dưới, lưu ý rằng `` use strict`` có thể được đặt ở đầu hàm (hầu hết các loại hàm) thay vì toàn bộ script. Sau đó chế độ nghiêm ngặt được bật trong chức năng đó. Nhưng thường mọi người sử dụng nó cho toàn bộ script. ````warn header="Ensure that \"use strict\" is at the top" -Please make sure that `"use strict"` is on the top of the script, otherwise the strict mode may not be enabled. +Chắc chắn rằng `"use strict"` được đặt vào đầu script, nếu không strict mode sẽ không hoạt động. -There is no strict mode here: +Ví dụ strict mode sẽ không hoạt động: ```js no-strict alert("some code"); @@ -40,24 +40,24 @@ alert("some code"); // strict mode is not activated ``` -Only comments may appear above `"use strict"`. +Chỉ có ghi chú có thể đặt trước `"use strict"`. ```` -```warn header="There's no way to cancel `use strict`" -There is no directive `"no use strict"` or alike, that would return the old behavior. +```warn header="Không có cách nào để hủy `use strict`" +Không có chỉ thị `"no use strict"` hay tương tự như thế. -Once we enter the strict mode, there's no return. +Khi đã dùng strict mode, không có cách nào quay lại và hủy bõ giữa chừng. ``` -## Always "use strict" +## Luôn luôn sử dụng "use strict" -The differences of `"use strict"` versus the "default" mode are still to be covered. +Sự khác biệt giữa `"use strict"` và "chế độ mặc định" là `"use strict"` được đảm bảo hơn. -In the next chapters, as we learn language features, we'll make notes about the differences of the strict mode. Luckily, there are not so many. And they actually make our life better. +Trong các chương kế tiếp, khi chúng ta học về các tính năng của JS, chúng ta sẽ thực hiện các ghi chú về sự khác biệt của chế độ nghiêm ngặt. May mắn thay, không có quá thay đổi. Và chúng thực sự làm cho code của chúng ta tốt hơn. -At this point in time it's enough to know about it in general: +Nói chung: -1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details as we study. -2. The strict mode is enabled by `"use strict"` at the top. Also there are several language features like "classes" and "modules" that enable strict mode automatically. -3. The strict mode is supported by all modern browsers. -4. It's always recommended to start scripts with `"use strict"`. All examples in this tutorial assume so, unless (very rarely) specified otherwise. +1. Dùng chỉ thị `"use strict"` để engine chạy ở chế độ hiện đại, thay đổi các hành vi của một vài tính năng có sẵn. Chúng ta sẽ thấy rõ hơn khi học các bài tiếp theo. +2. Chế độ nghiêm ngặt được bật lên bằng cách đặt `"use strict"` vào đầu script. Cũng có vài tính năng như "classes" và "modules" được bật strict mode một cách tự động. +3. Chế độ nghiêm ngặt được hỗ trợ bởi hầu hết các trình duyệt hiện nay. +4. Khuyên bạn nên dùng `"use strict"`. Tất cả các ví dụ trong tài liệu này đều dùng strict mode, rất rất hiếm khi dùng kiểu mặc định. From 77374714add7a031e1c5b457cd2d5e64cfb3e4bd Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 22:08:51 +0700 Subject: [PATCH 12/78] sdf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ádf --- 1-js/02-first-steps/03-strict-mode/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/03-strict-mode/article.md b/1-js/02-first-steps/03-strict-mode/article.md index 1d74559e27..af5678462b 100644 --- a/1-js/02-first-steps/03-strict-mode/article.md +++ b/1-js/02-first-steps/03-strict-mode/article.md @@ -1,4 +1,4 @@ -# Chế độ hiện đại Strict mode, "use strict" +# Chế độ nghiêm ngặt Strict mode, "use strict" Trong một thời gian dài JavaScript đã được phát triển mà không có vấn đề gì về tương thích. Các tính năng mới được thêm vào ngôn ngữ, đồng thời chức năng cũ không thay đổi. From f573d7836f6f918e668f486413647533f4d6d8ac Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 23:47:30 +0700 Subject: [PATCH 13/78] Vn Translate to VN --- 1-js/02-first-steps/04-variables/article.md | 196 ++++++++++---------- 1 file changed, 96 insertions(+), 100 deletions(-) diff --git a/1-js/02-first-steps/04-variables/article.md b/1-js/02-first-steps/04-variables/article.md index fe50cc52ae..c06fcec7dc 100644 --- a/1-js/02-first-steps/04-variables/article.md +++ b/1-js/02-first-steps/04-variables/article.md @@ -1,36 +1,36 @@ -# Variables +# Biến số - Variables -Most of the time, a JavaScript application needs to work with information. Here are 2 examples: -1. An online-shop -- the information might include goods being sold and a shopping cart. -2. A chat application -- the information might include users, messages, and much more. +Hầu hết thời gian ứng dụng JavaScript sẽ làm việc với các thông tin. Ví dụ: +1. Một shop online -- Thông tin có thể bao gồm hàng hóa, đơn hàng, kho bãi, giỏ hàng người dùng mua... +2. Một ứng dụng Chat -- Thông tin bao gồm người sử dụng, tin nhắn .... -Variables are used to store this information. +Biến sẽ được sử dụng để lưu trữ tất cả các thông tin trên. [cut] -## A variable +## biến số -A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goodies, visitors and other data. +Một biến [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) là một cái tên và lưu trữ thông tin nào đó. -To create a variable in JavaScript, we need to use the `let` keyword. +Để tạo ra biến trong JavaScript, cần dùng từ khóa `let`. -The statement below creates (in other words: *declares* or *defines*) a variable with the name "message": +Câu lệnh phía dưới tạo ra (khai báo) một biến có tên là "message": ```js let message; ``` -Now we can put some data into it by using the assignment operator `=`: +Chúng ta gán cho nó một giá trị bằng phép gán `=`: ```js let message; *!* -message = 'Hello'; // store the string +message = 'Hello'; // gán một chuỗi cho biến */!* ``` -The string is now saved into the memory area associated with the variable. We can access it using the variable name: +Chuỗi này sẽ được lưu trong vùng bộ nhớ có địa chỉ liên kết với biến. Chúng ta sử dụng biến như sau: ```js run let message; @@ -41,7 +41,7 @@ alert(message); // shows the variable content */!* ``` -To be concise we can merge the variable declaration and assignment into a single line: +Để ngắn gọn thì chúng ta có thể khai báo biến đồng thời gán giá trị cho nó trên một dòng: ```js run let message = 'Hello!'; // define the variable and assign the value @@ -49,15 +49,15 @@ let message = 'Hello!'; // define the variable and assign the value alert(message); // Hello! ``` -We can also declare multiple variables in one line: +Có thể khai báo nhiều biến trên một dòng: ```js no-beautify let user = 'John', age = 25, message = 'Hello'; ``` -That might seem shorter, but it's not recommended. For the sake of better readability, please use a single line per variable. +Nhìn gọn hơn nhưng việc này không khuyến khích. Để dễ đọc hơn, nên khai báo mỗi biến trên một dòng. -The multiline variant is a bit longer, but easier to read: +Tốn nhiều dòng nhưng sẽ dễ đọc hơn: ```js let user = 'John'; @@ -65,14 +65,14 @@ let age = 25; let message = 'Hello'; ``` -Some people also write many variables like that: +Nhiều người hay khai báo biến như thế này: ```js no-beautify let user = 'John', age = 25, message = 'Hello'; ``` -...Or even in the "comma-first" style: +...thậm chí như này: ```js no-beautify let user = 'John' @@ -80,32 +80,30 @@ let user = 'John' , message = 'Hello'; ``` -Technically, all these variants do the same. So, it's a matter of personal taste and aesthetics. +Về kỹ thuật thì các cách trên đều như nhau, nói chung là sở thích cá nhân và thẫm mỹ mỗi người. -````smart header="`var` instead of `let`" -In older scripts you may also find another keyword: `var` instead of `let`: +````smart header="`var` thay vì `let`" +Trong JS cũ bạn thường thấy từ khóa: `var` thay vì `let`: ```js *!*var*/!* message = 'Hello'; ``` -The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" fashion. +Từ khóa `var` gần giống như `let`. Cũng là khai báo biến nhưng nó đã xưa rồi. -There are subtle differences between `let` and `var`, but they do not matter for us yet. We'll cover them in detail later, in the chapter . +Có một sự khác biệt tinh tế giữa `let` và `var`, nhưng hiện tại không phải là vấn đề gì, chúng ta sẽ quan tâm việc này chi tiết hơn ở chương . ```` -## A real-life analogy +## Một vài ví dụ về biến trong cuộc sống -We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a uniquely-named sticker on it. +Chúng ta có thể dễ dàng nắm bắt khái niệm về một "biến số" nếu chúng ta tưởng tượng nó như là một "hộp" chứa đồ, với nhãn dán là duy nhất là tên biến, và cái thứ mà nó chứa đựng là giá trị của nó. -For instance, the variable `message` can be imagined as a box labelled `"message"` with the value `"Hello!"` in it: +Ví dụ biến `message` là một cái hộp có nhãn là `"message"` và giá trị `"Hello!"` nằm trong nó: ![](variable.png) -We can put any value into the box. - -Also we can change it. The value can be changed as many times as needed: +Chúng ta có thể đặt bất cứ thứ gì vào hộp hay nói cách khác là gán bất kỳ giá trị nào cho biến: ```js run let message; @@ -117,11 +115,11 @@ message = 'World!'; // value changed alert(message); ``` -When the value is changed, the old data is removed from the variable: +Khi thay đổi giá trị, giá trị cũ sẽ bị xóa khỏi biến: ![](variable-change.png) -We can also declare two variables and copy data from one into the other. +Chúng ta có thể khai báo 2 biến và copy giá trị biến này cho biến kia. ```js run let hello = 'Hello world!'; @@ -138,33 +136,33 @@ alert(hello); // Hello world! alert(message); // Hello world! ``` -```smart header="Functional languages" -It may be interesting to know that there also exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages that forbid changing a variable value. For example, [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/). +```smart header="Ngôn ngữ hàm" +Có thể bạn sẽ thấy thú vị khi biết có [ngôn ngữ lập trình hàm](https://en.wikipedia.org/wiki/Functional_programming) cấm việc thay đổi giá trị biến. Ví dụ, [Scala](http://www.scala-lang.org/) hoặc [Erlang](http://www.erlang.org/). -In such languages, once the value is stored "in the box", it's there forever. If we need to store something else, the language forces us to create a new box (declare a new variable). We can't reuse the old one. +Trong các ngôn ngữ đó biến không bao giờ thay đổi giá trị. Chỉ có cách tạo ra biến mới để lưu trữ giá trị khác. -Though it may seem a little bit odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if not planning to use it soon) is recommended to broaden the mind. +Hơn thế nữa, có những lĩnh vực như tính toán song song, trong đó sự hạn chế này lại là ưu điểm. Học một ngôn ngữ như vậy (ngay cả khi không có kế hoạch sử dụng nó sớm) được khuyến khích để mở rộng tầm nhìn của bạn. ``` -## Variable naming [#variable-naming] +## Đặt tên biến [#variable-naming] -There are two limitations for a variable name in JavaScript: +Có hai nguyên tắc đặt tên biến trong JavaScript: -1. The name must contain only letters, digits, symbols `$` and `_`. -2. The first character must not be a digit. +1. Tên biến chỉ gồm các chữ cái, chữ số và có thể có thêm 2 ký tự `$` và `_`. +2. Ký tự đầu tiên không thể là chữ số. -Valid names, for instance: +ví dụ về tên đúng: ```js let userName; let test123; ``` -When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another, each word starts with a capital letter: `myVeryLongName`. +Khi tên biến gồm nhiều từ, [camelCase](https://en.wikipedia.org/wiki/CamelCase) là cách hay dùng. Từ tiếp theo sau từ đầu tiên sẽ viết hoa chữ cái đầu tiên, ví dụ: `myVeryLongName`. -What's interesting -- the dollar sign `'$'` and the underscore `'_'` can also be used in names. They are regular symbols, just like letters, without any special meaning. +Dấu đô la `'$'` và gạch dưới `'_'` là các ký tự tiêu chuẩn như các chữ cái, không có ý nghĩa đặc biệt gì khác. -These names are valid: +Ví dụ tên đúng: ```js run untrusted let $ = 1; // declared a variable with the name "$" @@ -173,7 +171,7 @@ let _ = 2; // and now a variable with the name "_" alert($ + _); // 3 ``` -Examples of incorrect variable names: +Ví dụ tên sai: ```js no-beautify let 1a; // cannot start with a digit @@ -181,27 +179,28 @@ let 1a; // cannot start with a digit let my-name; // a hyphen '-' is not allowed in the name ``` -```smart header="Case matters" -Variables named `apple` and `AppLE` -- are two different variables. +```smart header="Viết hoa và viết thường" +Biến `apple` và `AppLE` -- là hai biến khác nhau. ``` -````smart header="Non-english letters are allowed, but not recommended" -It is possible to use any language, including cyrillic letters or even hieroglyphs, like this: +````smart header="Sử dụng các ngôn ngữ không phải tiếng Anh để đặt tên không được khuyến khích" +ví dụ: ```js let имя = '...'; let 我 = '...'; +let Cửa_hàng = 'xxx'; ``` -Technically, there is no error here, such names are allowed, but there is an international tradition to use English in variable names. Even if we're writing a small script, it may have a long life ahead. People from other countries may need to read it some time. +Về mặt kỹ thuật, không có lỗi ở đây, tên như vậy được cho phép, nhưng có một truyền thống quốc tế để sử dụng tiếng Anh trong các tên biến. Ngay cả khi chúng ta viết một kịch bản nhỏ. Những người từ các nước khác có thể cần phải đọc nó. ```` -````warn header="Reserved names" -There is a list of reserved words, which cannot be used as variable names, because they are used by the language itself. +````warn header="Các tên đã được sử dụng" +Có những từ không được lấy ra để đặt tên vì nó là từ khóa đã được JS sử dụng rồi. -For example, words `let`, `class`, `return`, `function` are reserved. +ví dụ, từ `let`, `class`, `return`, `function` . -The code below gives a syntax error: +Đoạn code sau sẽ xảy ra lỗi cú pháp: ```js run no-beautify let let = 5; // can't name a variable "let", error! @@ -209,9 +208,9 @@ let return = 5; // also can't name it "return", error! ``` ```` -````warn header="An assignment without `use strict`" +````warn header="Phép gán không sử dụng `use strict`" -Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value, without `let`. This still works now if we don't put `use strict`. The behavior is kept for compatibility with old scripts. +Thông thường, chúng ta cần xác định một biến trước khi sử dụng nó. Nhưng trước đây, về mặt kỹ thuật, có thể tạo ra một biến bằng cách gán một giá trị, mà không cần khai báo `let`. Điều này vẫn hoạt động được nếu chúng ta không đặt `use strict`. Các hành vi sẽ được giữ tương thích với các kịch bản cũ. ```js run no-strict // note: no "use strict" in this example @@ -221,7 +220,7 @@ num = 5; // the variable "num" is created if didn't exist alert(num); // 5 ``` -That's a bad practice, it gives an error in the strict mode: +Code dưới sẽ gây lỗi vì có strict mode: ```js run untrusted "use strict"; @@ -233,15 +232,15 @@ num = 5; // error: num is not defined ```` -## Constants +## Hằng số -To declare a constant (unchanging) variable, one can use `const` instead of `let`: +Để khai báo hằng (không thể thay đổi giá trị) dùng từ khóa `const` thay vì `let`: ```js const myBirthday = '18.04.1982'; ``` -Variables declared using `const` are called "constants". They cannot be changed. An attempt to do it would cause an error: +Có thể coi hằng là biến được khai báo bằng từ khóa `const` . Hằng thì không thể thay đổi giá trị, ví dụ code sau sẽ lỗi: ```js run const myBirthday = '18.04.1982'; @@ -249,16 +248,16 @@ const myBirthday = '18.04.1982'; myBirthday = '01.01.2001'; // error, can't reassign the constant! ``` -When a programmer is sure that the variable should never change, he can use `const` to guarantee it, and also to clearly show that fact to everyone. +Khi bạn chắc chắn rằng một biến sẽ không bao giờ thay đổi giá trị thì nên dùng `const` để đảm bảo cho nó, và cũng là để cho người khác đọc code của bạn có thể thấy điều đó. -### Uppercase constants +### Hằng với tên được viết hoa -There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution. +Có một thực tế phổ biến để sử dụng hằng số làm tên cho các giá trị khó nhớ được biết đến trước khi thực hiện. -Such constants are named using capital letters and underscores. +Các hằng số này được đặt tên bằng chữ hoa và dấu gạch dưới. -Like this: +Ví dụ: ```js run const COLOR_RED = "#F00"; @@ -271,64 +270,61 @@ let color = COLOR_ORANGE; alert(color); // #FF7F00 ``` -Benefits: +Ưu điểm: -- `COLOR_ORANGE` is much easier to remember than `"#FF7F00"`. -- It is much easier to mistype in `"#FF7F00"` than in `COLOR_ORANGE`. -- When reading the code, `COLOR_ORANGE` is much more meaningful than `#FF7F00`. +- `COLOR_ORANGE` dễ nhớ hơn là `"#FF7F00"`. +- `"#FF7F00"` dễ bị gõ sai hơn `COLOR_ORANGE`. +- Khi đọc code, `COLOR_ORANGE` có ngữ nghĩa hơn `#FF7F00`. -When should we use capitals for a constant, and when should we name them normally? Let's make that clear. +Khi nào nên dùng chữ hoa đặt tên cho biến, khi nào nên dùng chữ thường? Chúng ta cùng làm rõ. -Being a "constant" just means that the value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red), and there are those that are *calculated* in run-time, during the execution, but do not change after the assignment. +Trường hợp là hằng số và chúng ta không biết giá trị khởi tạo ban đầu của nó. Mặc dù là giá trị này sẽ không thay đổi. -For instance: +Ví dụ: ```js -const pageLoadTime = /* time taken by a webpage to load */; +const pageLoadTime = /* Thời gian để load một trang web */; ``` -The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant, because it doesn't change after assignment. - -In other words, capital-named constants are only used as aliases for "hard-coded" values. - -## Name things right +Giá trị của hằng `pageLoadTime` không được biết trước khi chúng ta tải trang web. Nhưng sau khi được gán, nó sẽ không thay đổi -Talking about variables, there's one more extremely important thing. +Trong các trường còn lại, các giá trị khó nhớ thì sử dụng hằng với tên được viết hoa và dấu gạch dưới. -Please name the variables sensibly. Take time to think if needed. +## Đặt tên mọi thứ sao cho đúng -Variable naming is one of the most important and complex skills in programming. A quick glance at variable names can reveal which code is written by a beginner and which by an experienced developer. +Nói về biến thì việc này vô cùng quan trọng. -In a real project, most of the time is spent on modifying and extending the existing code base, rather than writing something completely separate from scratch. And when we return to the code after some time of doing something else, it's much easier to find information that is well-labelled. Or, in other words, when the variables have good names. +Hãy đặt tên cho hợp lý, bõ thời gian suy nghĩ nếu cần. -Please spend some time thinking about the right name for a variable before declaring it. That will repay you a lot. +Đặt tên biến là một kỹ năng quan trọng và phức tạp trong lập trình. Nhìn qua tên biến là biết được code được viết bởi gà hay pro :D. -Some good-to-follow rules are: +Trong các dự án thật, hầu hết thời gian là dùng để chỉnh sửa và mở rộng code đã có sẵn. Và khi chúng ta nhìn lại code đã làm, sẽ dễ dang hơn để tìm thông tin thích hợp và đặt tên cho biến. -- Use human-readable names like `userName` or `shoppingCart`. -- Stay away from abbreviations or short names like `a`, `b`, `c`, unless you really know what you're doing. -- Make the name maximally descriptive and concise. Examples of bad names are `data` and `value`. Such a name says nothing. It is only ok to use them if it's exceptionally obvious from the context which data or value is meant. -- Agree on terms within your team and in your own mind. If a site visitor is called a "user" then we should name related variables like `currentUser` or `newUser`, but not `currentVisitor` or a `newManInTown`. +Hãy suy nghĩ để đặt tên thích hợp cho biến, việc này sẽ cực kỳ có ích cho bạn sau này. -Sounds simple? Indeed it is, but creating good descriptive-and-concise names in practice is not. Go for it. +Một vài cách ha như sau: -```smart header="Reuse or create?" -And the last note. There are some lazy programmers who, instead of declaring a new variable, tend to reuse the existing ones. +- Sử dụng các tên dễ đọc cho con người như `userName` hay `shoppingCart`. +- Tránh xa các chữ viết tắt hay tên ngắn `a`, `b`, `c`, trừ khi ban thực sự biết bạn đang làm gì. +- Đặt tên có ý nghĩa và súc tích nhất có thể. Ví dụ tên chả có ý nghĩa gì như `data` và `value`. Tên như vậy chả nói lên điều gì, trừ khi dùng trong một ngữ cảnh đặc biệt nào đó. +- Đồng ý với các quy định trong dự án hoặc phong cách bạn hay dùng. Nếu người dùng truy cập trang web của bạn được đặt tên là "user" thì nên dùng các biến liên quan như `currentUser` hoặc `newUser`, chứ không nên dùng `currentVisitor` hoặc `newManInTown`. -As a result, the variable is like a box where people throw different things without changing the sticker. What is inside it now? Who knows... We need to come closer and check. +Nghe đơn giản không? Thực sự nó đơn giản mà. Nhưng trong thực tế để tạo ra các tên biến có tính mô tả sát sao và súc tích cũng không dễ đâu. Quất thôi -Such a programmer saves a little bit on variable declaration, but loses ten times more on debugging the code. +```smart header="Sử dụng lại hay tạo mới?" +Ghi chú cuối cùng. Một số lập trình viên rất lười, họ sử dụng lại các biến thay vì khai báo biến mới. +Kết quả là biến giống như cái thùng trong các ví dụ trước. Ai vứt cái gì vào cũng được, chả ai biết trong đó có gì. -An extra variable is good, not evil. +Các bố này tiết kiệm được một chút công sức khai báo nhưng lại mất cả đống thời gian để debug lỗi sau này. -Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine to optimize. +Các trình chỉnh sửa của JavaScript và trình duyệt hiện đại tối ưu hóa mã khá tốt, vì vậy nó sẽ không tạo ra các vấn đề hiệu năng. Sử dụng các biến khác nhau cho các giá trị khác nhau thậm chí có thể giúp engine tối ưu hóa tốt hơn. ``` -## Summary +## Tổng kết -We can declare variables to store data. That can be done using `var` or `let` or `const`. +Chúng ta có thể khai báo biến để lưu trữ thông tin bằng cách dùng `var` hoặc `let` hoặc `const`. -- `let` -- is a modern variable declaration. The code must be in strict mode to use `let` in Chrome (V8). -- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter , just in case you need them. -- `const` -- is like `let`, but the value of the variable can't be changed. +- `let` -- là cách khai báo hiện đại. Code nên được dùng ở chế độ strict mode để dùng `let` trong Chrome (V8). +- `var` -- là cách khai báo xưa cũ. Thường chúng ta sẽ không sử dụng, Nhưng chúng ta sẽ tìm hiểu sự khác biệt của `var` và `let` trong chương . +- `const` -- giống như `let`, nhưng giá trị của biến sẽ không bao giờ thay đổi. -Variables should be named in a way that allows us to easily understand what's inside. +Biến nên được đặt tên sao cho dễ hiểu nhất, dễ nhận biết nhất biến này dùng để làm gì, lưu giữ thông tin gì. From a34e60fec40a00440c8b5660de2b1e6204ac09e2 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 23:48:03 +0700 Subject: [PATCH 14/78] vn vn --- 1-js/02-first-steps/04-variables/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/04-variables/article.md b/1-js/02-first-steps/04-variables/article.md index c06fcec7dc..949a9d8bd4 100644 --- a/1-js/02-first-steps/04-variables/article.md +++ b/1-js/02-first-steps/04-variables/article.md @@ -8,7 +8,7 @@ Biến sẽ được sử dụng để lưu trữ tất cả các thông tin tr [cut] -## biến số +## Biến số Một biến [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) là một cái tên và lưu trữ thông tin nào đó. From 117b8aaec1f283d001a62d486c5dbb751f18eda4 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 23:50:33 +0700 Subject: [PATCH 15/78] sdf sf --- .../02-first-steps/04-variables/1-hello-variables/task.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/02-first-steps/04-variables/1-hello-variables/task.md b/1-js/02-first-steps/04-variables/1-hello-variables/task.md index 84f009e8c7..6979f4b59b 100644 --- a/1-js/02-first-steps/04-variables/1-hello-variables/task.md +++ b/1-js/02-first-steps/04-variables/1-hello-variables/task.md @@ -4,7 +4,7 @@ importance: 2 # Working with variables -1. Declare two variables: `admin` and `name`. -2. Assign the value `"John"` to `name`. -3. Copy the value from `name` to `admin`. -4. Show the value of `admin` using `alert` (must output "John"). +1. Khai báo hai biến: `admin` và `name`. +2. Gán giá trị `"John"` cho biến `name`. +3. Copy giá trị từ biến `name` sang `admin`. +4. show giá trị biến `admin` sử dụng lệnh `alert` (kết quả "John"). From 740e5d56c126c16625e64cd4fff6af6fd3b05aac Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 23:52:18 +0700 Subject: [PATCH 16/78] =?UTF-8?q?=C4=91s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ds --- .../02-first-steps/04-variables/2-declare-variables/task.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/04-variables/2-declare-variables/task.md b/1-js/02-first-steps/04-variables/2-declare-variables/task.md index 21631e2600..139d76bdea 100644 --- a/1-js/02-first-steps/04-variables/2-declare-variables/task.md +++ b/1-js/02-first-steps/04-variables/2-declare-variables/task.md @@ -2,7 +2,7 @@ importance: 3 --- -# Giving the right name +# Đặt tên đúng -1. Create the variable with the name of our planet. How would you name such a variable? -2. Create the variable to store the name of the current visitor. How would you name that variable? +1. Đặt tên biến là hành tinh chúng ta đang sống. +2. Đặt tên biến là người dùng đang ghé thăm trang web. From 1adc35ecd8c20cf88c914d02cca5798268b68efa Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 6 Oct 2017 23:57:25 +0700 Subject: [PATCH 17/78] Update solution.md --- .../04-variables/2-declare-variables/solution.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/1-js/02-first-steps/04-variables/2-declare-variables/solution.md b/1-js/02-first-steps/04-variables/2-declare-variables/solution.md index 69aa3558d4..3a5c8d449a 100644 --- a/1-js/02-first-steps/04-variables/2-declare-variables/solution.md +++ b/1-js/02-first-steps/04-variables/2-declare-variables/solution.md @@ -1,21 +1,21 @@ -First, the variable for the name of our planet. +Có bố nào đặt tên biến là `earth` không đó ? -That's simple: +Đơn giản đáp án là: ```js let ourPlanetName = "Earth"; ``` -Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong. +Có thể đơn giản dùng `planet`, nhưng hành tinh gì, vẫn thiếu ý nghĩa, đặt ourPlanerName cũng không dài. -Second, the name of the current visitor: +Thứ hai là Người ghé thăm hiện thời trang web: ```js let currentUserName = "John"; ``` -Again, we could shorten that to `userName` if we know for sure that the user is current. +Có thể dùng `userName` nếu chắc chắn là hiện thời "current". -Modern editors and autocomplete make long variable names easy to write. Don't save on them. A name with 3 words in it is fine. +Các Editor có thể auto-complete cho bạn. Nên đừng tiết kiệm, cứ đặt tên dài không sao. -And if your editor does not have proper autocompletion, get [a new one](/editors). +Và nếu Editor không có chức năng autocompletion, dùng cái khác nhé [a new one](/editors). From e5a39ab091f7fe786bd7bb2c74cb1c1ea4e2bab7 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 7 Oct 2017 00:00:07 +0700 Subject: [PATCH 18/78] Update task.md --- .../04-variables/3-uppercast-constant/task.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md b/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md index 5fd18f90a8..aba15f8196 100644 --- a/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md +++ b/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md @@ -4,7 +4,7 @@ importance: 4 # Uppercase const? -Examine the following code: +Kiểm tra đoạn mã sau đây: ```js const birthday = '18.04.1982'; @@ -12,9 +12,9 @@ const birthday = '18.04.1982'; const age = someCode(birthday); ``` -Here we have a constant `birthday` date and the `age` is calculated from `birthday` with the help of some code (it is not provided for shortness, and because details don't matter here). +Hằng số `birthday` và `age` được tính toán từ `birthday` từ một vài tính toán nào đó `someCode`. -Would it be right to use upper case for `birthday`? For `age`? Or even for both? +Có nên đặt tên kiểu viết hoa cho `birthday`? và `age`? hay cả hai? ```js const BIRTHDAY = '18.04.1982'; // make uppercase? From 67d2525ac14edbf610479dcff26efc2c2225daa7 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 7 Oct 2017 20:42:14 +0700 Subject: [PATCH 19/78] Update article.md --- 1-js/02-first-steps/05-types/article.md | 159 ++++++++++++------------ 1 file changed, 80 insertions(+), 79 deletions(-) diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md index 3225221318..d4392b8bbc 100644 --- a/1-js/02-first-steps/05-types/article.md +++ b/1-js/02-first-steps/05-types/article.md @@ -1,6 +1,6 @@ -# Data types +# Kiểu dữ liệu - Data types -A variable in JavaScript can contain any data. A variable can at one moment be a string and later receive a numeric value: +Biến trong JavaScript có thể chứa dữ liệu nào đó và đồng thời có thể thay đổi giá trị: ```js // no error @@ -8,65 +8,65 @@ let message = "hello"; message = 123456; ``` -Programming languages that allow such things are called "dynamically typed", meaning that there are data types, but variables are not bound to any of them. +Ngôn ngữ lập trình như vậy được gọi là động "dynamically typed", có nghĩa là có nhiều kiểu dữ liệu trong ngôn ngữ, nhưng các biến không bị ràng buộc bởi chúng. -There are seven basic data types in JavaScript. Here we'll study the basics, and in the next chapters we'll talk about each of them in detail. +có 7 kiểu dữ liệu cơ bản trong JavaScript. Chúng ta học sơ qua về từng loại dữ liệu sau đó sẽ tìm hiểu kỹ mỗi loại ở các chương tiếp theo. [cut] -## A number +## Kiểu số - number ```js let n = 123; n = 12.345; ``` -The *number* type serves both for integer and floating point numbers. +Kiểu *number* bao gồm số nguyên và số thực. -There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, subtraction `-` and so on. +Trên kiểu số có các phép toán như: nhân `*`, chia `/`, cộng `+`, trừ `-` và một số phép toán khác nữa. -Besides regular numbers, there are so-called "special numeric values" which also belong to that type: `Infinity`, `-Infinity` and `NaN`. +Bên cạnh các số cụ thể còn có các số đặc biệt như: dương vô cùng - `Infinity`, âm vô cùng - `-Infinity` và số không xác định `NaN`. -- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity) ∞. It is a special value that's greater than any number. +- `Infinity` dương vô cùng [Infinity](https://en.wikipedia.org/wiki/Infinity) ∞. là một số dương lớn vô cùng. - We can get it as a result of division by zero: + Chúng ta nhận được nó khi chia một số dương cho số 0: ```js run alert( 1 / 0 ); // Infinity ``` - Or just mention it in the code directly: + Hoặc có thể dùng trực tiếp như này: ```js run alert( Infinity ); // Infinity ``` -- `NaN` represents a computational error. It is a result of an incorrect or an undefined mathematical operation, for instance: +- `NaN` là số không xác định, hay là kết quả của một phép toán vô nghĩa trong toán học, hoặc phép toán lỗi: ```js run alert( "not a number" / 2 ); // NaN, such division is erroneous ``` - `NaN` is sticky. Any further operation on `NaN` would give `NaN`: + Một phép toán bất kỳ có chứa `NaN` sẽ trả về kết quả là `NaN`: ```js run alert( "not a number" / 2 + 5 ); // NaN ``` - So, if there's `NaN` somewhere in a mathematical expression, it propagates to the whole result. + Cho nên chỉ cần thấy `NaN` trong bất kỳ biểu thức nào thì kết quả trả về sẽ là Nan. -```smart header="Mathematical operations are safe" -Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc. +```smart header="Các phép toán là an toàn" +Tính toán toán học trong JavaScript là an toàn. Hơi khác với trong toán học, vì nó tồn tai các phép toán như: chia cho 0, phép toán trên các giá trị không phải là số. -The script will never stop with a fatal error ("die"). At worst we'll get `NaN` as the result. +Script sẽ không bao giờ lỗi và stop chương trình bởi các phép toán, vì cùng lắm là trả về `NaN`. ``` -Special numeric values formally belong to the "number" type. Of course they are not numbers in a common sense of this word. +Các số đặc biệt cũng là kiểu số đấy nhé. Tất nhiên là trong JS chứ không phải trong thế giới thực. -We'll see more about working with numbers in the chapter . +Chúng ta sẽ học kỹ hơn ở chương . -## A string +## Chuỗi - string -A string in JavaScript must be quoted. +Chuỗi trong JavaScript phải đặt trong dấu nháy đơn hoặc nháy kép. ```js let str = "Hello"; @@ -74,15 +74,15 @@ let str2 = 'Single quotes are ok too'; let phrase = `can embed ${str}`; ``` -In JavaScript, there are 3 types of quotes. +Trong JavaScript, Có ba kiểu dấu nháy. -1. Double quotes: `"Hello"`. -2. Single quotes: `'Hello'`. -3. Backticks: `Hello`. +1. Nháy kép: `"Hello"`. +2. Nháy đơn: `'Hello'`. +3. và dấu nháy Backticks: `Hello`. -Double and single quotes are "simple" quotes. There's no difference between them in JavaScript. +Nháy đơn và nháy kép là dấu nháy đơn giản, có ý nghĩa như nhau trong JavaScript. -Backticks are "extended functionality" quotes. They allow us to embed variables and expressions into a string by wrapping them in `${…}`, for example: +Backticks dấu nháy "chức năng mở rộng". Dạng như template vậy, nó cho phép nhúng biến vào trong biểu thức `${…}`, Ví dụ: ```js run let name = "John"; @@ -94,35 +94,35 @@ alert( `Hello, *!*${name}*/!*!` ); // Hello, John! alert( `the result is *!*${1 + 2}*/!*` ); // the result is 3 ``` -The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex. +Biểu thức trong `${…}` sẽ được đánh giá và tính toán, sau đó kết quả sẽ là một phần của chuỗi. chúng ta có thể để vào bất cứ thứ gì: một biến `name` hoặc một biểu thức đơn giản như `1 + 2` hay nhiều thứ phức tạp hơn. -Please note that this can only be done in backticks. Other quotes do not allow such embedding! +Chỉ backticks mới được nhé, nháy đơn hay nháy kép không chấp nhận kiểu nhúng này ```js run alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing) ``` -We'll cover strings more thoroughly in the chapter . +Chúng ta sẽ học kỹ hơn trong chương . -```smart header="There is no *character* type." -In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is `char`. +```smart header="Không có kiểu ký tự - *character*." +Trong các ngôn ngữ khác như C sẽ có kiểu ký tự đơn `char`. -In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them. +Trong JavaScript, Không có kiểu char như vậy mà chỉ có một kiểu `string` cho ký tự đơn hay một chuỗi dài nhiều ký tự. ``` -## A boolean (logical type) +## Kiểu logic - boolean -The boolean type has only two values: `true` and `false`. +Kiểu boolean chỉ có hai giá trị là đúng: `true` và sai: `false`. -This type is commonly used to store yes/no values: `true` means "yes, correct", and `false` means "no, incorrect". +Thường được dùng để lưu các giá trị yes/no. -For instance: +Ví dụ: ```js let nameFieldChecked = true; // yes, name field is checked let ageFieldChecked = false; // no, age field is not checked ``` -Boolean values also come as a result of comparisons: +Giá trị kiểu Boolean cũng là kết quả của một phép so sánh: ```js run let isGreater = 4 > 1; @@ -130,31 +130,32 @@ let isGreater = 4 > 1; alert( isGreater ); // true (the comparison result is "yes") ``` -We'll cover booleans more deeply later in the chapter . +Sẽ học kỹ hơn về Boolean trong chương . -## The "null" value +## Giá trị "null" -The special `null` value does not belong to any type of those described above. +Giá trị đặc biệt `null` Không thuộc bất cứ một kiểu dữ liệu nào ở trên. -It forms a separate type of its own, which contains only the `null` value: +`null` thuộc kiểu null, hay nói cách khác kiểu null chỉ gồm một giá trị là `null` . +Có nhiều bạn nói null là kiểu Object, các bạn cứ đọc tiếp sẽ có phần giải thích nhé: ```js let age = null; ``` -In JavaScript `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages. +Trong JavaScript `null` không phải là "tham chiếu đến một đối tượng không tồn tại" hoặc "con trỏ mà không trỏ đến bất cứ cái gì" như các ngôn ngữ khác. -It's just a special value which has the sense of "nothing", "empty" or "value unknown". +Nó chỉ là một giá trị thể hiện sự không có gì: "nothing", trống rỗng: "empty" hoặc không biết giá trị: "value unknown". -The code above states that the `age` is unknown or empty for some reason. +Code bên trên người ta khai báo biến `age` là chưa biết hoặc không chứa giá trị vì một lý do nào đó. -## The "undefined" value +## Giá trị chưa được định ngĩa - "undefined" -The special value `undefined` stands apart. It makes a type of its own, just like `null`. +`undefined` thuộc kiểu undefined, kiểu như `null`. -The meaning of `undefined` is "value is not assigned". +`undefined` để thể hiện cho "chưa được gán giá trị". -If a variable is declared, but not assigned, then its value is exactly `undefined`: +Nếu một biến được khai báo nhưng chưa được gán giá trị nào, thì giá trị của biến đó chính là `undefined`: ```js run let x; @@ -162,7 +163,7 @@ let x; alert(x); // shows "undefined" ``` -Technically, it is possible to assign `undefined` to any variable: +Về mặt kỹ thuật, có thể gán giá trị `undefined` cho bất cứ biến nào: ```js run let x = 123; @@ -172,28 +173,28 @@ x = undefined; alert(x); // "undefined" ``` -...But it's not recommended to do that. Normally, we use `null` to write an "empty" or an "unknown" value into the variable, and `undefined` is only used for checks, to see if the variable is assigned or similar. +...Nhưng không khuyến khích làm như thế. Bình thường chúng ta dùng `null` để thể hiện một biến có giá trị là trống "empty" hoặc chưa biết, và `undefined` chỉ để kiểm tra là biến đã được gán giá trị hay chưa. -## Objects and Symbols +## Kiểu đối tượng - Object và kiểu Symbol (méo biết dịch ra là gì) -The `object` type is special. +Kiểu `object` là kiểu đặc biệt. -All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities. We'll deal with them later in the chapter after we know enough about primitives. +Tất cả các kiểu dữ liệu khác được gọi là kiểu nguyên thủy "primitive", bởi vì giá trị của chúng chưa những thành phần đơn lẽ. Ngược lại Objects chứa một bộ giá trị phức tạp. Chúng ta sẽ học thêm ở chương sau khi có đủ hiểu biết về các kiểu primitives. -The `symbol` type is used to create unique identifiers for objects. We have to mention it here for completeness, but it's better to study them after objects. +Kiểu `symbol` để tạo ra các giá trị duy nhất - unique identifiers cho Objects. Chúng ta chỉ nhắc đến tên nó ở đây cho biết vậy thôi, để sau khi học xong về kiểu Objects sẽ quay lại học về nó sẽ dễ hiểu hơn. -## The typeof operator [#type-typeof] +## Phép toán typeof [#type-typeof] -The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently, or just want to make a quick check. +Phép toán `typeof` trả về kiểu dữ liệu của tham số. Người ta hay dùng để kiểm tra hay so kiểu dữ liệu. -It supports two forms of syntax: +Có thể dùng theo hai cách: -1. As an operator: `typeof x`. -2. Function style: `typeof(x)`. +1. Như một phép toán: `typeof x`. +2. Như hàm: `typeof(x)`. -In other words, it works both with parentheses or without them. The result is the same. +Hai cách này cho kết quả như nhau. -The call to `typeof x` returns a string with the type name: +Gọi `typeof x` trả về một *String* là tên kiểu dữ liệu: ```js typeof undefined // "undefined" @@ -221,27 +222,27 @@ typeof alert // "function" (3) The last three lines may need additional explanations: -1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter . Here it serves just as an example of an object. -2. The result of `typeof null` is `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, that's an error in the language. -3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the next chapters, and we'll see that there's no special "function" type in the language. Functions belong to the object type. But `typeof` treats them differently. Formally, it's incorrect, but very convenient in practice. +1. `Math` là một đối tượng được JS xây dựng sẵn, chứa các phép tính toán học. Chúng ta sẽ tìm hiểu ở chương . Lấy ra làm ví dụ ở đây cho kiểu Object thôi. +2. Kết quả của `typeof null` là `"object"`. Điều này là sai. Đó là lỗi chính thức được thừa nhận trong `typeof`, để giữ cho sự tương thích của nó. Tất nhiên, `null` không phải là một Object. Nó là một giá trị đặc biệt và thuộc kiểu null. Một lần nữa, khẳng định là tồn tại lỗi này trong JS nhé. +3. Kết quả của `typeof alert` là `"function"`, bởi vì `alert` là một hàm. Chúng ta sẽ học về hàm trong chương tiếp theo, và chúng ta sẽ thấy không có kiểu hàm đặc biệt nào trong JS. fuction là kiểu Object. Nhưng `typeof` xác định nó hơi khác. Thực sự thì là không đúng, nhưng như thế thì sẽ tiện lợi hơn khi dùng. -## Summary +## Tóm tắt -There are 7 basic types in JavaScript. +Có 7 kiểu dữ liệu cơ bản trong JavaScript. -- `number` for numbers of any kind: integer or floating-point. -- `string` for strings. A string may have one or more characters, there's no separate single-character type. -- `boolean` for `true`/`false`. -- `null` for unknown values -- a standalone type that has a single value `null`. -- `undefined` for unassigned values -- a standalone type that has a single value `undefined`. -- `object` for more complex data structures. -- `symbol` for unique identifiers. +- `number` cho số nguyên và số thực. +- `string` cho chuỗi và ký tự. +- `boolean` cho đúng/sai `true`/`false`. +- `null` cho giá trị chưa rõ -- có kiểu là chính nó, giống thằng `null`. +- `undefined` cho chưa gán giá trị -- cũng là kiểu `undefined`. +- `object` cho các cấu trúc dữ liệu phức tạp. +- `symbol` cho định danh duy nhất. -The `typeof` operator allows us to see which type is stored in the variable. +Phép toán `typeof` cho chúng ta biết kiểu dữ liệu của tham số. -- Two forms: `typeof x` or `typeof(x)`. -- Returns a string with the name of the type, like `"string"`. -- For `null` returns `"object"` -- that's an error in the language, it's not an object in fact. +- có thể dùng theo hai cách: `typeof x` or `typeof(x)`. +- Trả về một string với hai dấu nháy kép, ví dụ: `"string"`. +- typeof `null` trả về `"object"` -- Đây là lỗi trong JS, thực sự nó không phải là Object. -In the next chapters we'll concentrate on primitive values and once we're familiar with them, then we'll move on to objects. +Chương tiếp chúng ta sẽ tập trung vào các kiểu primitive sau khi đã quen thuộc sẽ nghiên cứu tiếp về objects. From 254f37abcd8f820e9608e043995eec353390b73c Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 7 Oct 2017 20:45:17 +0700 Subject: [PATCH 20/78] Update article.md --- 1-js/02-first-steps/05-types/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md index d4392b8bbc..2cffe9561f 100644 --- a/1-js/02-first-steps/05-types/article.md +++ b/1-js/02-first-steps/05-types/article.md @@ -1,4 +1,4 @@ -# Kiểu dữ liệu - Data types +# Các kiểu dữ liệu - Data types Biến trong JavaScript có thể chứa dữ liệu nào đó và đồng thời có thể thay đổi giá trị: From 8c3f2207e6d0a816b81c978ab0aabc1f0da1d030 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 14:48:45 +0700 Subject: [PATCH 21/78] Update article.md --- .../06-type-conversions/article.md | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/1-js/02-first-steps/06-type-conversions/article.md b/1-js/02-first-steps/06-type-conversions/article.md index df14571ad6..365261ade5 100644 --- a/1-js/02-first-steps/06-type-conversions/article.md +++ b/1-js/02-first-steps/06-type-conversions/article.md @@ -1,24 +1,24 @@ -# Type Conversions +# Ép kiểu -Most of the time, operators and functions automatically convert a value to the right type. That's called "type conversion". +Trong JS, các phép toán và hàm thường thực hiện chuyển đổi giá trị về đúng kiểu dữ liệu trước khi thực hiện tính toán. Chúng ta gọi đó là ép kiểu hay "type conversion". -For example, `alert` automatically converts any value to a string to show it. Mathematical operations convert values to numbers. +Ví dụ, `alert` sẽ tự động chuyển đổi bất cứ giá trị nào thành `string` trước khi show ra màn hình. Hay các phép tính toán toán học thì convert giá trị về kiểu số. -There are also cases when we need to explicitly convert a value to put things right. +Trong nhiều trường hợp chúng ta cần sự chuyển đổi này một cách rõ ràng để code được chính xác. [cut] -```smart header="Not talking about objects yet" -In this chapter we don't cover objects yet. Here we study primitives first. Later, after we learn objects, we'll see how object conversion works in the chapter . +```smart header="Chưa nói về Object" +Chương này chưa nói về Object. Học về các kiểu primitives trước. Sau đó sẽ học về Object và học luôn ép kiểu trên Object ở chương . ``` ## ToString -String conversion happens when we need the string form of a value. +Ép kiểu string xảy ra khi cần một giá trị đưa vào là string. -For example, `alert(value)` does it to show the value. +Ví dụ, `alert(value)` sẽ show lên giá trị của `value`. -We can also use a call `String(value)` function for that: +Chúng ta cũng có thể dùng `String(value)` để ép kiểu sang string: ```js run let value = true; @@ -30,19 +30,19 @@ alert(typeof value); // string */!* ``` -String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc. +Ép kiểu string là chuyển đổi nguyên dạng. VD: `false` thành `"false"`, `null` thành `"null"` vv. ## ToNumber -Numeric conversion happens in mathematical functions and expressions automatically. +Ép kiểu number xảy ra trong các hàm hoặc biểu thức toán học. -For example, when division `/` is applied to non-numbers: +Ví dụ khi dùng phép chia `/` trên các giá trị không phải number: ```js run alert( "6" / "2" ); // 3, strings are converted to numbers ``` -We can use a `Number(value)` function to explicitly convert a `value`: +Cũng có thể dùng `Number(value)` để chuyển đổi `value` sang kiểu number một cách rõ ràng: ```js run let str = "123"; @@ -53,9 +53,9 @@ let num = Number(str); // becomes a number 123 alert(typeof num); // number ``` -Explicit conversion is usually required when we read a value from a string-based source like a text form, but we expect a number to be entered. +Chuyển đổi number một cách rõ ràng thường được dùng khi input dạng text và chúng ta mong muốn nhận được là một giá trị số. -If the string is not a valid number, the result of such conversion is `NaN`, for instance: +Nếu chuỗi nhập vào là không phải "dạng số" thì sẽ trả về `NaN`, Ví dụ: ```js run let age = Number("an arbitrary string instead of a number"); @@ -63,16 +63,16 @@ let age = Number("an arbitrary string instead of a number"); alert(age); // NaN, conversion failed ``` -Numeric conversion rules: +Quy tắc ép kiểu number: | Value | Becomes... | |-------|-------------| |`undefined`|`NaN`| |`null`|`0`| -|true and false | `1` and `0` | -| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. | +|true and false | `1` và `0` | +| `string` | Dấu space bắt đầu chuỗi bị loại bõ. Nếu chuỗi là rỗng thì trả về `0`. Ngược lại sẽ tiến hành chuyển đổi. Nếu có lỗi sẽ trả về `NaN`. | -Examples: +Ví dụ: ```js run alert( Number(" 123 ") ); // 123 @@ -81,33 +81,33 @@ alert( Number(true) ); // 1 alert( Number(false) ); // 0 ``` -Please note that `null` and `undefined` behave differently here: `null` becomes a zero, while `undefined` becomes `NaN`. +Lưu ý rằng `null` và `undefined` sẽ được chuyển đổi khác nhau: `null` trả về 0, trong khi `undefined` trả về `NaN`. -````smart header="Addition '+' concatenates strings" -Almost all mathematical operations convert values to numbers. With a notable exception of the addition `+`. If one of the added values is a string, then another one is also converted to a string. +````smart header="Phép '+' nối chuỗi" +Hầu hết các phép tính toán học sẽ chuyển đổi giá trị sang số. ngoại truwfp phép `+`. Nếu có một số hạng là string, thì sẽ chuyển đổi sang string, và tiến hành nối chuỗi. -Then it concatenates (joins) them: +Ví dụ: ```js run alert( 1 + '2' ); // '12' (string to the right) alert( '1' + 2 ); // '12' (string to the left) ``` -That only happens when one of the arguments is a string. Otherwise, values are converted to numbers. +Điều này xảy ra chỉ khi một trong hai số hạng là string. ```` ## ToBoolean -Boolean conversion is the simplest one. +Ép kiểu logic thì đơn giản hơn. -It happens in logical operations (later we'll meet condition tests and other kinds of them), but also can be performed manually with the call of `Boolean(value)`. +Xảy ra trong các phép logic, hoặc chuyển đổi một cách rõ ràng với `Boolean(value)`. -The conversion rule: +Quy ước: -- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`. -- Other values become `true`. +- Các giá trị thể hiện sự trống rỗng như `0`, một chuỗi rỗng, `null`, `undefined` và `NaN` sẽ trả về `false`. +- Các giá trị khác trả về `true`. -For instance: +Ví dụ: ```js run alert( Boolean(1) ); // true @@ -117,8 +117,8 @@ alert( Boolean("hello") ); // true alert( Boolean("") ); // false ``` -````warn header="Please note: the string with zero `\"0\"` is `true`" -Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript a non-empty string is always `true`. +````warn header="Chú ý là chuỗi `\"0\"` trả về `true`" +Một số NNLT (như PHP) thì chuỗi `"0"` trả về `false`, khác với JavaScript nhé. ```js run alert( Boolean("0") ); // true @@ -127,36 +127,36 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true) ```` -## Summary +## Tóm tắt -There are three most widely used type conversions: to string, to number and to boolean. +Có ba kiểu ép kiểu phổ biến: to string, to number và to boolean. -**`ToString`** -- Occurs when we output something, can be performed with `String(value)`. The conversion to string is usually obvious for primitive values. +**`ToString`** -- xảy ra khi cần output dạng string. hoặc có thể dùng `String(value)`. Sự chuyển đổi là nguyên bản. -**`ToNumber`** -- Occurs in math operations, can be performed with `Number(value)`. +**`ToNumber`** -- Xảy ra trong các phép tính toán toán học . hoặc có thể dùng `Number(value)`. -The conversion follows the rules: +Sự chuyển đổi number tuân theo nguyên tắc: | Value | Becomes... | |-------|-------------| |`undefined`|`NaN`| |`null`|`0`| |true / false | `1 / 0` | -| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string becomes `0`. An error gives `NaN`. | +| `string` | chuyển đổi như sô được nhập vào dạng text, bỏ qua khoảng trắng hai đầu. Chuỗi rỗng "" trả về `0`. Có lỗi trả về `NaN`. | -**`ToBoolean`** -- Occurs in logical operations, or can be performed with `Boolean(value)`. +**`ToBoolean`** -- Xảy ra trong các tính toán logic, hoặc có thể dùng `Boolean(value)`. -Follows the rules: +Theo nguyên tắc: | Value | Becomes... | |-------|-------------| |`0`, `null`, `undefined`, `NaN`, `""` |`false`| -|any other value| `true` | +|Giá trị khác| `true` | -Most of these rules are easy to understand and memorize. The notable exceptions where people usually make mistakes are: +Hầu hết các quy tắc đều dễ hiểu và dễ nhớ, nhưng có một vài điểm mà mọi người hay nhầm lẫn như sau: -- `undefined` is `NaN` as a number, not `0`. -- `"0"` and space-only strings like `" "` are true as a boolean. +- `undefined` trả về `NaN` là một số, cứ không phải trả về `0`. +- `"0"` và chuỗi toàn dấu space `" "` trả `true` trong ép kiểu boolean. -Objects are not covered here, we'll return to them later in the chapter that is devoted exclusively to objects, after we learn more basic things about JavaScript. +Ép kiểu Object không nói ở bài này, chúng ta sẽ học ở chương . From 43356aca2718d07d893abc24a91becabd85323d9 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 14:49:35 +0700 Subject: [PATCH 22/78] Update article.md --- 1-js/02-first-steps/06-type-conversions/article.md | 1 - 1 file changed, 1 deletion(-) diff --git a/1-js/02-first-steps/06-type-conversions/article.md b/1-js/02-first-steps/06-type-conversions/article.md index 365261ade5..3d915bbe01 100644 --- a/1-js/02-first-steps/06-type-conversions/article.md +++ b/1-js/02-first-steps/06-type-conversions/article.md @@ -153,7 +153,6 @@ Theo nguyên tắc: |`0`, `null`, `undefined`, `NaN`, `""` |`false`| |Giá trị khác| `true` | - Hầu hết các quy tắc đều dễ hiểu và dễ nhớ, nhưng có một vài điểm mà mọi người hay nhầm lẫn như sau: - `undefined` trả về `NaN` là một số, cứ không phải trả về `0`. From 98f038ea18c1d30b44774f035a275dba0f5d87d3 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 14:58:23 +0700 Subject: [PATCH 23/78] Update article.md --- 1-js/02-first-steps/06-type-conversions/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/06-type-conversions/article.md b/1-js/02-first-steps/06-type-conversions/article.md index 3d915bbe01..745917f177 100644 --- a/1-js/02-first-steps/06-type-conversions/article.md +++ b/1-js/02-first-steps/06-type-conversions/article.md @@ -124,9 +124,9 @@ Một số NNLT (như PHP) thì chuỗi `"0"` trả về `false`, khác với Ja alert( Boolean("0") ); // true alert( Boolean(" ") ); // spaces, also true (any non-empty string is true) ``` +Các bạn cẩn thận nhầm chỗ này ```` - ## Tóm tắt Có ba kiểu ép kiểu phổ biến: to string, to number và to boolean. From 7fdf046de682a7c00d7ff3d757bcee7893492cfb Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 15:09:14 +0700 Subject: [PATCH 24/78] Update task.md --- .../1-primitive-conversions-questions/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md index 83b295f927..394cda4b7e 100644 --- a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md +++ b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md @@ -4,7 +4,7 @@ importance: 5 # Type conversions -What are results of these expressions? +Kết quả của các biểu thức sau là? ```js no-beautify "" + 1 + 0 @@ -23,4 +23,4 @@ null + 1 undefined + 1 ``` -Think well, write down and then compare with the answer. +Làm và so sánh với đáp án nhé. From a3fa1e9cbbbbbedbcb0278eb1ee811974203db61 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 15:12:17 +0700 Subject: [PATCH 25/78] Update solution.md --- .../1-primitive-conversions-questions/solution.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md index a4f3fec7ae..ccbcb43298 100644 --- a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md +++ b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md @@ -16,7 +16,7 @@ null + 1 = 1 // (3) undefined + 1 = NaN // (4) ``` -1. The addition with a string `"" + 1` converts `1` to a string: `"" + 1 = "1"`, and then we have `"1" + 0`, the same rule is applied. -2. The subtraction `"-"` (like most math operations) only works with numbers, it converts an empty string `""` to `0`. -3. `null` becomes `0` after the numeric conversion. -4. `undefined` becomes `NaN` after the numeric conversion. +1. Phép cộng với một chuỗi `"" + 1` chuyển đổi `1` về kiểu string: `"" + 1 = "1"`, tiếp theo `"1" + 0`, cho ra kq như trên. +2. Phép trừ `"-"` thì luôn chuyển đổi sang number, nó chuyển đổi `""` thành `0`. +3. `null` thành `0` sau khi ép kiểu number. +4. `undefined` thành `NaN` sau khi ép kiểu number. From 853c47ae10c7f88c00518783151114b9b140859f Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 16:46:32 +0700 Subject: [PATCH 26/78] Update article.md --- 1-js/02-first-steps/07-operators/article.md | 106 ++++++++++---------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/1-js/02-first-steps/07-operators/article.md b/1-js/02-first-steps/07-operators/article.md index df24311c63..6da6d5b1e1 100644 --- a/1-js/02-first-steps/07-operators/article.md +++ b/1-js/02-first-steps/07-operators/article.md @@ -1,17 +1,17 @@ -# Operators +# Các phép toán -Many operators are known to us from school. They are addition `+`, a multiplication `*`, a subtraction `-` and so on. +Một vài phép toán chúng ta đã biết khi học ở trường. Như `+`, `-`, `*`, `/`, và vv. -In this chapter we concentrate on aspects that are not covered by school arithmetic. +Trong chương này chúng ta sẽ tập trung vào các ngoại lệ, hay sự khác biệt trong các phép toán trong JS và toán học. [cut] -## Terms: "unary", "binary", "operand" +## Quy tắc: Một ngôi "unary", hai ngôi "binary" và toán hạng "operand" -Before we move on, let's grasp the common terminology. +Trước khi tiếp tục, chúng ta hãy nắm bắt các thuật ngữ phổ biến. -- *An operand* -- is what operators are applied to. For instance in multiplication `5 * 2` there are two operands: the left operand is `5`, and the right operand is `2`. Sometimes people say "arguments" instead of "operands". -- An operator is *unary* if it has a single operand. For example, the unary negation `"-"` reverses the sign of the number: +- *Toán hạng - An operand* -- là đối tượng của phép toán. Ví dụ trong phép nhân `5 * 2` có hai toán hạng: toán hạng bên trái là `5`, và toán hạng bên phải là `2`. Thỉnh thoảng người ta cũng gọi là tham số "arguments" thay vì toán hạng "operands". +- Phép toán là một ngôi *unary* nếu chỉ có 1 toán hạng. Ví dụ phép `"-"` đổi dấu một số: ```js run let x = 1; @@ -21,55 +21,53 @@ Before we move on, let's grasp the common terminology. */!* alert( x ); // -1, unary negation was applied ``` -- An operator is *binary* if it has two operands. The same minus exists in the binary form as well: +- Phép toán là hai ngôi *binary* nếu có 2 toán hạng, tương tự n ngôi nếu có n toán hạng: ```js run no-beautify let x = 1, y = 3; alert( y - x ); // 2, binary minus subtracts values ``` - Formally, we're talking about two different operators here: the unary negation (single operand, reverses the sign) and the binary subtraction (two operands, subtracts). + Chúng ta chủ yếu nói đến sự khác nhau giữa hai phép toán: the unary negation (phép đổi dấu) và the binary subtraction (phép trừ hai số). -## Strings concatenation, binary + +## phép + là một phép toán hai ngôi - binary + -Now let's see special features of JavaScript operators that are beyond school arithmetics. +Chúng ta sẽ xem xem JS khác tóa học như thế nào. -Usually the plus operator `'+'` sums numbers. +Thông thường phép `'+'` để cộng các số. -But if the binary `+` is applied to strings, it merges (concatenates) them: +nhưng nếu binary `+` mà có 1 toán hạng là string, thì thành phép nối chuỗi: ```js let s = "my" + "string"; alert(s); // mystring ``` -Note that if any of operands is a string, then the other one is converted to a string too. +Chú ý là nếu có 1 toán hạng là string thì toán hạng kia sẽ được chuyển đổi thành string. -For example: +Ví dụ: ```js run alert( '1' + 2 ); // "12" alert( 2 + '1' ); // "21" ``` -See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, then convert the other one into a string as well. - -String concatenation and conversion is a special feature of the binary plus `"+"`. Other arithmetic operators work only with numbers. They always convert their operands to numbers. +Trong JS phép `"+"` hơi đặc biệt. Các phép toán học khác chỉ làm việc với number, Còn phép + có thể làm việc với number và string. -For instance, subtraction and division: +Ví dụ phép trừ và phép chia: ```js run alert( 2 - '1' ); // 1 alert( '6' / '2' ); // 3 ``` -## Numeric conversion, unary + +## Ép kiểu number, unary + -The plus `+` exist in two forms. The binary form that we used above and the unary form. +Phép `+` có thể là phép toán 2 ngôi hoặc cũng có thể là 1 ngôi. -The unary plus or, in other words, the plus operator `+` applied to a single value, doesn't do anything with numbers, but if the operand is not a number, then it is converted into it. +Phép `+` một ngôi đơn giản là chính nó. Tương tự như toán học vậy. -For example: +Ví dụ: ```js run // No effect on numbers @@ -86,13 +84,11 @@ alert( +"" ); // 0 */!* ``` -It actually does the same as `Number(...)`, but shorter. - -A need to convert string to number arises very often. For example, if we are getting values from HTML form fields, then they are usually strings. +Nó tương đương với `Number(...)`, nhưng viết ngắn hơn. -What if we want to sum them? +Nhu cầu chuyển đổi string sang số là khá nhiều. VD: Viết chương trình cộng 2 số được nhập từ bàn phím. Hay chuyển đổi giá trị nào đó từ form HTML -The binary plus would add them as strings: +VD: ```js run let apples = "2"; @@ -101,7 +97,7 @@ let oranges = "3"; alert( apples + oranges ); // "23", the binary plus concatenates strings ``` -If we want to treat them as numbers, then we can convert and then sum: +Nếu muốn là number thì ta làm như sau: ```js run let apples = "2"; @@ -116,42 +112,42 @@ alert( +apples + +oranges ); // 5 // alert( Number(apples) + Number(oranges) ); // 5 ``` -From a mathematician's standpoint the abundance of pluses may seem strange. But from a programmer's standpoint, there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up. +Theo quan điểm toán học, viết các dấu + như vậy có vẻ là lạ, nhưng trên quan điểm tin học, điều đó là bình thường: unary + được ưu tiên trước, chuyển đổi strings sang numbers, và sau đó binary + sẽ cộng chúng lại. -Why are unary pluses applied to values before the binary one? As we're going to see, that's because of their *higher precedence*. +Tại sao phép toán một ngôi lại được tính trước phép toán hai ngôi? Vì theo quy ước nó được ưu tiên hơn *higher precedence*. -## Operators precedence +## Độ ưu tiên của các phép toán -If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, there's an implicit priority order among the operators. +Nếu một biểu thức có nhiều phép toán thì thằng nào tính trước, thằng nào tính sau? -From school we all know that the multiplication in the expression `1 + 2 * 2` should be calculated before the addition. That's exactly the precedence thing. The multiplication is said to have *a higher precedence* than the addition. +Ở trường các bạn được học là nhân chia trước, cộng trừ sau. Ví dụ `1 + 2 * 2` cho ra kết quả là 5, ta nói phép nhân có độ ưu tiên cao hơn phép cộng. -Parentheses override any precedence, so if we're not satisfied with the order, we can use them, like: `(1 + 2) * 2`. +Biểu thức trong ngoặc thì sẽ tính trước, Ví dụ trên nếu muốn phép cộng tính trước thì ta viết `(1 + 2) * 2`. -There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the bigger number executes first. If the precedence is the same, the execution order is from left to right. +Trong JavaScript. Phép toán có độ ưu tiên cao hơn thì được thực thi trước, nếu có độ ưu tiên bằng nhau thì thực thi từ trái sang phải. -An extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (you don't need to remember this, but note that unary operators are higher than corresponding binary ones): +Chi tiết độ ưu tiên các bạn có thể xem tại [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) Không cần bạn phải nhớ chi tiết, Đơn giản chỉ cần nhớ là phép toán một ngôi sẽ có độ ưu tiên cao hơn phép toán hai ngôi: -| Precedence | Name | Sign | +| Độ ưu tiên | Phép toán | ký tự | |------------|------|------| | ... | ... | ... | -| 16 | unary plus | `+` | -| 16 | unary negation | `-` | -| 14 | multiplication | `*` | -| 14 | division | `/` | -| 13 | addition | `+` | -| 13 | subtraction | `-` | +| 16 | Cộng một ngôi | `+` | +| 16 | đổi dấu | `-` | +| 14 | nhân | `*` | +| 14 | chia | `/` | +| 13 | cộng | `+` | +| 13 | trừ | `-` | | ... | ... | ... | -| 3 | assignment | `=` | +| 3 | gán | `=` | | ... | ... | ... | -As we can see, the "unary plus" has a priority of `16`, which is higher than `13` for the "addition" (binary plus). That's why in the expression `"+apples + +oranges"` unary pluses work first, and then the addition. +Ta có thể thấy "Phép cộng một ngôi" có độ ưu tiên là `16`, cao hơn phép cộng hai ngôi có độ ưu tiên `13` . Đó là lý do tại sao trong biểu thức `"+apples + +oranges"` Phép cộng một ngôi được tính trước. -## Assignment +## Phép gán -Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `3`. +Chú ý rằng phép gán `=` cũng là một phép toán. Và nó có độ ưu tiên khá thấp là `3`. -That's why when we assign a variable, like `x = 2 * 2 + 1`, then the calculations are done first, and afterwards the `=` is evaluated, storing the result in `x`. +Đó là lý do tại sao khi ta gán, ví dụ `x = 2 * 2 + 1`, thì giá trị được tính toán trước rồi mới gán `=` cho `x`. ```js let x = 2 * 2 + 1; @@ -159,7 +155,7 @@ let x = 2 * 2 + 1; alert( x ); // 5 ``` -It is possible to chain assignments: +Cũng có thể gán chồng nhau nhiều lần như thế nào: ```js run let a, b, c; @@ -173,14 +169,14 @@ alert( b ); // 4 alert( c ); // 4 ``` -Chained assignments evaluate from right to left. First the rightmost expression `2 + 2` is evaluated then assigned to the variables on the left: `c`, `b` and `a`. At the end, all variables share a single value. +Gán chồng nhau sẽ thực hiện từ phải qua trái `2 + 2` ra `4` gán cho `c`, `b` rồi đến `a`. -````smart header="The assignment operator `\"=\"` returns a value" -An operator always returns a value. That's obvious for most of them like an addition `+` or a multiplication `*`. But the assignment operator follows that rule too. +````smart header="Phép gán `\"=\"` trả về giá trị" +Các phép toán trả về giá trị là kết quả của phép toán đó. ví dụ `5 + 5` kết quả là 10, và cũng là `return 10`. Tương tự phép gán cũng thế. -The call `x = value` writes the `value` into `x` *and then returns it*. +Ví dụ `x = value` gán `value` cho `x` *và cũng: return value*. -Here's the demo that uses an assignment as part of a more complex expression: +Ví dụ phức tạp hơn: ```js run let a = 1; From a9d1db576c9d03b6839749c2d95f6ccb40173146 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 20:26:53 +0700 Subject: [PATCH 27/78] Update article.md --- 1-js/02-first-steps/07-operators/article.md | 118 ++++++++++---------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/1-js/02-first-steps/07-operators/article.md b/1-js/02-first-steps/07-operators/article.md index 6da6d5b1e1..1ace04b392 100644 --- a/1-js/02-first-steps/07-operators/article.md +++ b/1-js/02-first-steps/07-operators/article.md @@ -190,18 +190,18 @@ alert( a ); // 3 alert( c ); // 0 ``` -In the example above, the result of `(a = b + 1)` is the value which is assigned to `a` (that is `3`). It is then used to subtract from `3`. +Ở ví dụ trên, kết quả `(a = b + 1)` là giá trị gán cho `a` (đó là `3`). sau đó thực hiện phép trừ `3 - 3`. -Funny code, isn't it? We should understand how it works, because sometimes we can see it in 3rd-party libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make the code clearer and readable. +Code trên cho vui để hiểu thêm thôi, chứ không nên viết kiểu thách đố như vậy không hay lắm. ```` -## Remainder % +## Phép thặng dư % -The remainder operator `%` despite its look does not have a relation to percents. +Phép thặng dư `%` , không phải là phần trăm đâu nhé :D . -The result of `a % b` is the remainder of the integer division of `a` by `b`. +Kết quả của `a % b` là phân dư của phép chia nguyên `a` cho `b`. -For instance: +ví dụ: ```js run alert( 5 % 2 ); // 1 is a remainder of 5 divided by 2 @@ -209,13 +209,13 @@ alert( 8 % 3 ); // 2 is a remainder of 8 divided by 3 alert( 6 % 3 ); // 0 is a remainder of 6 divided by 3 ``` -## Exponentiation ** +## Lũy thừa ** -The exponentiation operator `**` is a recent addition to the language. +Phép lũy thừa `**` vừa được thêm vào JS mới đây. -For a natural number `b`, the result of `a ** b` is `a` multiplied by itself `b` times. +Với số nguyên `b`, kết quả của `a ** b` là `a` lũy thừa `b`. -For instance: +Ví dụ: ```js run alert( 2 ** 2 ); // 4 (2 * 2) @@ -223,7 +223,7 @@ alert( 2 ** 3 ); // 8 (2 * 2 * 2) alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2) ``` -The operator works for non-integer numbers of `a` and `b` as well, for instance: +Cũng có thể thực hiện trên các số không nguyên `a` và `b` như ví dụ: ```js run alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths) @@ -234,18 +234,18 @@ alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root) -Increasing or decreasing a number by one is among the most common numerical operations. +Tăng một đơn vị ++ và giảm 1 đơn vị -- . -So, there are special operators for that: +Ví dụ: -- **Increment** `++` increases a variable by 1: +- **Increment** `++` tăng giá trị biến lên 1: ```js run no-beautify let counter = 2; counter++; // works same as counter = counter + 1, but shorter alert( counter ); // 3 ``` -- **Decrement** `--` decreases a variable by 1: +- **Decrement** `--` giảm giá trị đi 1: ```js run no-beautify let counter = 2; @@ -254,21 +254,21 @@ So, there are special operators for that: ``` ```warn -Increment/decrement can be applied only to a variable. An attempt to use it on a value like `5++` will give an error. +Increment/decrement chỉ tác động lên biến. Nếu dùng vào hằng VD `5++` sẽ báo lỗi. ``` -Operators `++` and `--` can be placed both after and before the variable. +Phép `++` và `--` có thể dùng trước hoặc sau biến. -- When the operator goes after the variable, it is called a "postfix form": `counter++`. -- The "prefix form" is when the operator stands before the variable: `++counter`. +- Nếu dùng sau thì gọi là "postfix form": `counter++`. +- gọi là "prefix form" nếu dùng trước `++counter`. -Both of these records do the same: increase `counter` by `1`. +Cả hai cách đều là tăng `counter` lên `1`. -Is there any difference? Yes, but we can only see it if we use the returned value of `++/--`. +Hai cách dùng `++/--` có gì khác nhau không? Có khác, nhưng chúng ta chỉ thây sự khác biệt này khi dùng với `return` . -Let's clarify. As we know, all operators return a value. Increment/decrement is not an exception here. The prefix form returns the new value, while the postfix form returns the old value (prior to increment/decrement). +Như chúng ta đã biết, phép toán nào cũng trả về giá trị nào đó. Increment/decrement cũng không ngoại lệ. Dùng kiểu prefix form trả về giá trị mới, trong khi postfix form trả về giá trị cũ (trước khi tăng/giảm). -To see the difference, here's the example: +Để xem sự khác biệt này, cùng xem ví dụ sau: ```js run let counter = 1; @@ -277,9 +277,9 @@ let a = ++counter; // (*) alert(a); // *!*2*/!* ``` -Here in the line `(*)` the prefix call `++counter` increments `counter` and returns the new value that is `2`. So the `alert` shows `2`. +Dòng `(*)` Dùng kiểu prefix form `++counter` tăng `counter` lên một đơn vị và trả về *giá trị mới* là `2` và sau đó gán cho `a`. nên `alert` show ra `2`. -Now let's use the postfix form: +Bây giờ dùng thử postfix form: ```js run let counter = 1; @@ -288,11 +288,11 @@ let a = counter++; // (*) changed ++counter to counter++ alert(a); // *!*1*/!* ``` -In the line `(*)` the *postfix* form `counter++` also increments `counter`, but returns the *old* value (prior to increment). So the `alert` shows `1`. +Dòng `(*)` Dùng kiểu *postfix* form `counter++` cũng tăng `counter` lên 1, nhưng trả về *giá trị cũ* (trước khi tăng). Nên `alert` show ra `1`. -To summarize: +Tổng kết: -- If the result of increment/decrement is not used, then there is no difference in which form to use: +- Nếu kết quả của phép increment/decrement không được sử dụng ngay thì không thấy sự khác biệt giữa hai kiểu dùng: ```js run let counter = 0; @@ -300,41 +300,39 @@ To summarize: ++counter; alert( counter ); // 2, the lines above did the same ``` -- If we'd like to increase the value *and* use the result of the operator right now, then we need the prefix form: +- Nếu muốn tăng/giảm giá trị của biến và *dùng ngay* lập tức kết quả mới này thì dùng kiểu prefix form: ```js run let counter = 0; alert( ++counter ); // 1 ``` -- If we'd like to increment, but use the previous value, then we need the postfix form: +- Nếu tăng/giảm giá trị của biến nhưng vẫn sử dụng giá trị của nó khi chưa tăng/giảm thì dùng kiểu postfix form: ```js run let counter = 0; alert( counter++ ); // 0 ``` -````smart header="Increment/decrement among other operators" -Operators `++/--` can be used inside an expression as well. Their precedence is higher than most other arithmetical operations. +````smart header="Increment/decrement giữa các phép toán khác" +Phép `++/--` có thể sử dụng trong biểu thức. Độ ưu tiên của nó cao hơn các phép tính toán toán học. -For instance: +Ví dụ: ```js run let counter = 1; alert( 2 * ++counter ); // 4 ``` -Compare with: +So sánh với: ```js run let counter = 1; alert( 2 * counter++ ); // 2, because counter++ returns the "old" value ``` -Though technically allowable, such notation usually makes the code less readable. One line does multiple things -- not good. +Mặc dù không có lỗi gì, nhưng tính toán nhiều thứ trên một dòng thì khó đọc - not good. Nên viết tách ra. -While reading the code, a fast "vertical" eye-scan can easily miss such `counter++`, and it won't be obvious that the variable increases. - -The "one line -- one action" style is advised: +Nên dùng code kiểu "one line -- one action" - một dòng một hành động: ```js run let counter = 1; @@ -343,13 +341,13 @@ counter++; ``` ```` -## Bitwise operators +## Phép toán nhị phân -Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their binary representation. +Phép toán nhị phân đưa các tham số về dạng 32 bits số nguyên và thực hiện trên các bits đó. -These operators are not JavaScript-specific. They are supported in most programming languages. +Phép toán nhị phân không phải là đặc trưng của JS, nó chủ yếu cho các ngôn ngữ khác. -The list of operators: +Các phép toán nhị phân: - AND ( `&` ) - OR ( `|` ) @@ -359,13 +357,13 @@ The list of operators: - RIGHT SHIFT ( `>>` ) - ZERO-FILL RIGHT SHIFT ( `>>>` ) -These operators are used very rarely. To understand them, we should delve into low-level number representation, and it would not be optimal to do that right now. Especially because we won't need them any time soon. If you're curious, you can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article in MDN. It would be more practical to do that when a real need arises. +Trong JS hiếm khi bạn dùng đến các phép toán nhị phân. Nếu muốn hiểu thêm, có thể đọc tài liệu này [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators). ## Modify-in-place -We often need to apply an operator to a variable and store the new result in it. +Chúng ta thường cần sử dụng giá trị của biến sau một phép tính toán ở trên biến đó. -For example: +Ví dụ: ```js let n = 2; @@ -373,7 +371,7 @@ n = n + 5; n = n * 2; ``` -This notation can be shortened using operators `+=` and `*=`: +Có thể thực hiện nhanh việc này bằng `+=` và `*=`: ```js run let n = 2; @@ -383,9 +381,9 @@ n *= 2; // now n = 14 (same as n = n * 2) alert( n ); // 14 ``` -Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=` etc. +Kiểu như trên gọi là phép "modify-and-assign" , nó cũng hỗ trợ hầu hết các phép toán khác như: `/=`, `-=` etc. -Such operators have the same precedence as a normal assignment, so they run after most other calculations: +Các phép toán kiểu này có độ ưu tiên như phép gán, VD: ```js run let n = 2; @@ -395,13 +393,13 @@ n *= 3 + 5; alert( n ); // 16 (right part evaluated first, same as n *= 8) ``` -## Comma +## Dấu phẩy - Comma -The comma operator `','` is one of most rare and unusual operators. Sometimes it's used to write shorter code, so we need to know it in order to understand what's going on. +Dấu `','` là một phép toán hiếm khi được dùng. Nhưng thỉnh thoảng vẫn được sử dụng để viết code ngắn hơn -The comma operator allows us to evaluate several expressions, dividing them with a comma `','`. Each of them is evaluated, but the result of only the last one is returned. +Phép comma `','` để chia cách các biểu thức, nhưng sẽ chỉ lấy giá trị cuối cùng. -For example: +Ví dụ: ```js run *!* @@ -411,19 +409,19 @@ let a = (1 + 2, 3 + 4); alert( a ); // 7 (the result of 3 + 4) ``` -Here, the first expression `1 + 2` is evaluated, and its result is thrown away, then `3 + 4` is evaluated and returned as the result. +Ở đây, biểu thức `1 + 2` được tính toán nhưng kq bị bõ đi, sau đó `3 + 4` được tính toán và trả về. -```smart header="Comma has a very low precedence" -Please note that the comma operator has very low precedence, lower than `=`, so parentheses are important in the example above. +```smart header="Comma có độ ưu tiên rất thấp" +thấp hơn cả phép gán `=`, nên cần cặp dấu ngoặc như bạn thấy ở trên. -Without them: `a = 1 + 2, 3 + 4` evaluates `+` first, summing the numbers into `a = 3, 7`, then the assignment operator `=` assigns `a = 3`, and then the number after the comma `7` is not processed anyhow, so it's ignored. +Nếu không có cặp dấu ngoặc: `a = 1 + 2, 3 + 4` thực hiện `+` trước, và sẽ thành `a = 3, 7`, sau đó `=` gán `a = 3`, và cuối cùng số `7` được trả về cho biểu thức này. (a vẫn = 3 nhé) ``` -Why do we need such an operator which throws away everything except the last part? +Vậy tại sao lại dùng comma, đằng nào kq cũng bị bõ đi trừ biểu thức cuối cùng mà? -Sometimes people use it in more complex constructs to put several actions in one line. +Thỉnh thoảng người ta dùng nó để đưa vào những biểu thức phức tạp, thực hiện một loạt hành động trên một dòng. -For example: +ví dụ: ```js // three operations in one line @@ -432,4 +430,4 @@ for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) { } ``` -Such tricks are used in many JavaScript frameworks, that's why we mention them. But usually they don't improve the code readability, so we should think well before writing like that. +Mẹo này hay được dùng trong các JS FrameWork hiện nay, nên mình đưa ra đây cho các bạn biết. From cc42e63756d9751debb689677008010657ba34d7 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Mon, 9 Oct 2017 21:32:56 +0700 Subject: [PATCH 28/78] Update article.md --- 1-js/02-first-steps/08-comparison/article.md | 160 +++++++++---------- 1 file changed, 79 insertions(+), 81 deletions(-) diff --git a/1-js/02-first-steps/08-comparison/article.md b/1-js/02-first-steps/08-comparison/article.md index ed0034feec..5392cbb917 100644 --- a/1-js/02-first-steps/08-comparison/article.md +++ b/1-js/02-first-steps/08-comparison/article.md @@ -1,22 +1,22 @@ -# Comparisons +# Các phép so sánh -Many comparison operators we know from maths: +Một số phép so sánh chúng ta học được từ toán học như: -- Greater/less than: a > b, a < b. -- Greater/less than or equals: a >= b, a <= b. -- Equality check is written as `a == b` (please note the double equation sign `'='`. A single symbol `a = b` would mean an assignment). -- Not equals. In maths the notation is , in JavaScript it's written as an assignment with an exclamation sign before it: a != b. +- Lớn hơn, nhỏ hơn: a > b, a < b. +- Lớn hơn hoặc bằng, nhỏ hơn hoặc bằng: a >= b, a <= b. +- So sánh bằng `a == b` (chú ý hai dấu `'='` nhé. Một dấu `a = b` là phép gán). +- Không bằng (hay khác). Trong toán học là dấu , Trong JavaScript là dấu bằng với sự phủ định: a != b. [cut] -## Boolean is the result +## Boolean là kết quả của phép so sánh -Just as all other operators, a comparison returns a value. The value is of the boolean type. +Tất cả các phép toán đều trả về giá trị nào đó, và với phép so sánh nó trả về giá trị đúng/sai. -- `true` -- means "yes", "correct" or "the truth". -- `false` -- means "no", "wrong" or "a lie". +- `true` -- có ý nghĩa là "yes", "đúng" hay "sự thật". +- `false` -- có ý nghĩa là "no", "sai" hay "sự dối trá". -For example: +Ví dụ: ```js run alert( 2 > 1 ); // true (correct) @@ -24,20 +24,20 @@ alert( 2 == 1 ); // false (wrong) alert( 2 != 1 ); // true (correct) ``` -A comparison result can be assigned to a variable, just like any value: +Giá trị trả về của một phép so sánh có thể gán luôn cho biến nào đó: ```js run let result = 5 > 4; // assign the result of the comparison alert( result ); // true ``` -## String comparison +## So sánh chuỗi -To see which string is greater than the other, the so-called "dictionary" or "lexicographical" order is used. +Chuỗi lớn hơn nếu nó nằm sau trong bảng chữ cái (hoặc bảng mã). -In other words, strings are compared letter-by-letter. +Sự so sánh sẽ tiến hành theo từng chữ cái, từ trái sang phải. -For example: +VD: ```js run alert( 'Z' > 'A' ); // true @@ -45,53 +45,53 @@ alert( 'Glow' > 'Glee' ); // true alert( 'Bee' > 'Be' ); // true ``` -The algorithm to compare two strings is simple: +Quy tắc so sánh chuỗi đơn giản như sau: -1. Compare first characters of both strings. -2. If the first one is greater(or less), then the first string is greater(or less) than the second. We're done. -3. Otherwise if first characters are equal, compare the second characters the same way. -4. Repeat until the end of any string. -5. If both strings ended simultaneously, then they are equal. Otherwise the longer string is greater. +1. So sánh ký tự đầu tiên của hai chuỗi. +2. Thằng nào lớn hơn thì chuỗi đó lớn hơn. +3. Nếu bằng nhau thì so sánh ký tự tiếp theo. +4. Cứ tiếp tục như thế. +5. Nếu một chuỗi đã hết ký tự mà vẫn bằng nhau. Thì chuỗi nào dài hơn chuỗi đó sẽ lớn hơn -In the example above, the comparison `'Z' > 'A'` gets the result at the first step. +Ở ví dụ trên `'Z' > 'A'` trả về kết quả ngay bước đầu tiên. -Strings `"Glow"` and `"Glee"` are compared character-by-character: +Chuỗi `"Glow"` và `"Glee"` được so sánh từng ký tự: -1. `G` is the same as `G`. -2. `l` is the same as `l`. -3. `o` is greater than `e`. Stop here. The first string is greater. +1. `G` bằng `G`. +2. `l` bằng `l`. +3. `o` lớn hơn `e`. Xong, vậy chuỗi `"Glow"` lớn hơn. -```smart header="Not a real dictionary, but Unicode order" -The comparison algorithm given above is roughly equivalent to the one used in book dictionaries or phone books. But it's not exactly the same. +```smart header="Không phải bảng chữ cái mà là bãng mã Unicode" +Thực ra so sánh chuỗi không phải theo bãng chữ cái thông thường. -For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? Actually, the lowercase `"a"` is. Why? Because the lowercase character has a greater index in the internal encoding table (Unicode). We'll get back to specific details and consequences in the chapter . +Ví dụ chữ viết hoa `"A"` sẽ không bằng với `"a"`. Chữ `"a"` sẽ lớn hơn. Bởi vì nó có *mã* lớn hơn theo bãng mã (Unicode). Chúng ta sẽ tìm hiểu kỹ hơn ở chương . ``` -## Comparison of different types +## So sánh hai kiểu dữ liệu khác nhau -When compared values belong to different types, they are converted to numbers. +Khi so sánh khác kiểu, nó sẽ convert thành number. -For example: +ví dụ: ```js run alert( '2' > 1 ); // true, string '2' becomes a number 2 alert( '01' == 1 ); // true, string '01' becomes a number 1 ``` -For boolean values, `true` becomes `1` and `false` becomes `0`, that's why: +Với boolean, `true` trở thành `1` và `false` là `0`, đã học rồi: ```js run alert( true == 1 ); // true alert( false == 0 ); // true ``` -````smart header="A funny consequence" -It is possible that at the same time: +````smart header="Một kết quả thú vị" +Có thể cùng một lúc: -- Two values are equal. -- One of them is `true` as a boolean and the other one is `false` as a boolean. +- Hai giá trị bằng nhau. +- Một là `true` kiểu boolean và `false` cũng là kiểu boolean. -For example: +Ví dụ: ```js run let a = 0; @@ -102,71 +102,69 @@ alert( Boolean(b) ); // true alert(a == b); // true! ``` +Bạn nào thấy có gì đó sai sai thì đọc lại bài 6 nhé, đã học rồi. -From JavaScript's standpoint that's quite normal. An equality check converts using the numeric conversion (hence `"0"` becomes `0`), while `Boolean` conversion uses another set of rules. ```` -## Strict equality +## Strict equality - bằng (một cách nghiêm ngặt) -A regular equality check `"=="` has a problem. It cannot differ `0` from `false`: +Ta thấy phép so sánh `"=="` có vấn đề sau: nó không phân biệt được sự khác nhau giữ `0` và `false`: ```js run alert( 0 == false ); // true ``` -The same thing with an empty string: +Điều tương tự xảy ra với một chuỗi rỗng: ```js run alert( '' == false ); // true ``` -That's because operands of different types are converted to a number by the equality operator `==`. An empty string, just like `false`, becomes a zero. +Đó là bởi vì các toán hạng trong phép `==` đã được ép kiểu sang number rồi. Một chuỗi rỗng hay `false`, đều chuyển đổi thành `0`. -What to do if we'd like to differentiate `0` from `false`? +Để tìm sự khác biệt giữa `0` và `false` chúng ta làm sao đây? -**A strict equality operator `===` checks the equality without type conversion.** +**Phép `===` so sánh sự bằng nhau mà không chuyển đổi kiểu.** -In other words, if `a` and `b` are of different types, then `a === b` immediately returns `false` without an attempt to convert them. +Nói cách khác nếu `a` và `b` khác kiểu dữ liệu thì `a === b` luôn luôn trả về `false` . -Let's try it: +VD: ```js run alert( 0 === false ); // false, because the types are different ``` -There also exists a "strict non-equality" operator `!==`, as an analogy for `!=`. +Có một sự tương đương đối với cặp phép toán `!==` và `!=` nhé. -The strict equality check operator is a bit longer to write, but makes it obvious what's going on and leaves less space for errors. +## So sánh với null và undefined -## Comparison with null and undefined +Xem trường hợp sau. -Let's see more edge cases. +Khi so sánh `null` và `undefined` với các kiểu dữ liệu khác. -There's a non-intuitive behavior when `null` or `undefined` are compared with other values. - -For a strict equality check `===` -: These values are different, because each of them belong to a separate type of it's own. +Với phép `===` +: Hai giá trị là khác nhau bởi vì chúng thuộc kiểu dữ liệu là chính nó. ```js run alert( null === undefined ); // false ``` -For a non-strict check `==` -: There's a special rule. These two are a "sweet couple": they equal each other (in the sense of `==`), but not any other value. +Với phép `==` +: Có một quy định đặc biệt cho phép `null` và `undefined` bằng nhau, nhưng không bằng với bất kỳ giá trị nào khác. ```js run alert( null == undefined ); // true ``` -For maths and other comparisons `< > <= >=` -: Values `null/undefined` are converted to a number: `null` becomes `0`, while `undefined` becomes `NaN`. +Với so sánh toán học và các phép so sánh khác `< > <= >=` +: Giá trị `null/undefined` sẽ được chuyển đổi sang number: `null` thành `0`, `undefined` thành `NaN`. -Now let's see funny things that happen when we apply those rules. And, what's more important, how to not fall into a trap with these features. +Nào chúng ta xem một số sự đặc biệt dưới đây, phần này khá là quan trọng đấy -### Strange result: null vs 0 +### Kết quả kỳ lạ: null và 0 -Let's compare `null` with a zero: +So sánh `null` và `0`: ```js run alert( null > 0 ); // (1) false @@ -174,15 +172,15 @@ alert( null == 0 ); // (2) false alert( null >= 0 ); // (3) *!*true*/!* ``` -Yeah, mathematically that's strange. The last result states that "`null` is greater than or equal to zero". Then one of the comparisons above must be correct, but they are both false. +Thấy vl chưa các bạn. -The reason is that an equality check `==` and comparisons `> < >= <=` work differently. Comparisons convert `null` to a number, hence treat it as `0`. That's why (3) `null >= 0` is true and (1) `null > 0` is false. +Nguyên nhân là phép `==` và các phép so sánh `> < >= <=` làm việc khác nhau. Các phép so sánh convert `null` thành number, và kq là `0`. đó là vì sao (3) `null >= 0` là đúng và (1) `null > 0` là sai. -On the other hand, the equality check `==` for `undefined` and `null` works by the rule, without any conversions. They equal each other and don't equal anything else. That's why (2) `null == 0` is false. +Còn lại phép `==` cho `undefined` và `null` thì theo nguyên tắc như đã nói ở trên rồi, hai thằng này chỉ bằng nhau và không bằng bất cứ thằng nào khác. Do đó nên `null == 0` là sai. -### An incomparable undefined +### Không thể so sánh được undefined -The value `undefined` shouldn't participate in comparisons at all: +Giá trị `undefined` không nên đem ra so sánh ở bất kỳ trường hợp nào: ```js run alert( undefined > 0 ); // false (1) @@ -190,25 +188,25 @@ alert( undefined < 0 ); // false (2) alert( undefined == 0 ); // false (3) ``` -Why does it dislike a zero so much? Always false! +Luôn luôn là false! -We've got these results because: +Chúng ta giải thích các kết quả: -- Comparisons `(1)` and `(2)` return `false` because `undefined` gets converted to `NaN`. And `NaN` is a special numeric value which returns `false` for all comparisons. -- The equality check `(3)` returns `false`, because `undefined` only equals `null` and no other value. +- `(1)` và `(2)` return `false` vì `undefined` được convert thành `NaN`. Và `NaN` là một số đặc biệt. Trong mọi phép so sánh với `NaN` đều sẽ trả về `false` . +- `(3)` returns `false`, vì `undefined` chỉ bằng `null` ngoài ra chẳng bằng thằng nào khác. -### Evade problems +### Những vấn đề cần tránh -Why did we observe these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to evade any problems with them. +Tại sao chúng ta học những ví dụ này? Chúng ta có nên nhớ những đặc thù này không? Vâng, không thực sự. Trên thực tế, những điều khó hiểu này sẽ dần dần trở nên quen thuộc theo thời gian, nhưng có một cách để không bị dính vào những đặc thù này. -Just treat any comparison with `undefined/null` except the strict equality `===` with exceptional care. +Không nên so sánh với `undefined/null` trừ trường hợp dùng phép `===` với sự cẩn thận nhất có thể. -Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you are really sure what you're doing. If a variable can have such values, then check for them separately. +Không sử dụng các phép so sánh `>= > < <=` với giá trị có thể là `null/undefined`, trừ khi bạn biết mình đang làm gì. Nếu các biến có thể trả về `null/undefined` thì tốt nhất hãy tách chúng ra. -## Summary +## Tổng kết -- Comparison operators return a logical value. -- Strings are compared letter-by-letter in the "dictionary" order. -- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check). +- Các phép so sánh trả về giá trị logic. +- String được so sánh từ trái sang phải, theo thứ tự trong bảng mã Unicode. +- Khi so sánh hai giá trị khác kiểu dữ liệu, thì chúng sẽ được convert thành number trước (Chú ý ngoại lệ của phép `==`). - Values `null` and `undefined` equal `==` each other and do not equal any other value. -- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Making a separate check for `null/undefined` is a good idea. +- Cẩn thận khi so sánh `>` hoặc `<` với các giá trị có thể là `null/undefined`. Nên tách `null/undefined` ra. From 49247e72a34c61f1976876b0057db36938cb3e7e Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 10 Oct 2017 11:06:42 +0700 Subject: [PATCH 29/78] Update article.md --- .../09-alert-prompt-confirm/article.md | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/article.md b/1-js/02-first-steps/09-alert-prompt-confirm/article.md index 3b393fbc71..b3f3510ec4 100644 --- a/1-js/02-first-steps/09-alert-prompt-confirm/article.md +++ b/1-js/02-first-steps/09-alert-prompt-confirm/article.md @@ -1,50 +1,48 @@ -# Interaction: alert, prompt, confirm +# Một số lệnh tương tác: alert, prompt, confirm -This part of the tutorial aims to cover JavaScript "as is", without environment-specific tweaks. - -But still we use a browser as the demo environment. So we should know at least a few user-interface functions. In this chapter we'll get familiar with the browser functions `alert`, `prompt` and `confirm`. +Bài này chúng ta học về các hàm `alert`, `prompt` and `confirm`. [cut] ## alert -Syntax: +Cú pháp: ```js alert(message); ``` -This shows a message and pauses the script execution until the user presses "OK". +Show một tin nhắn lên màn hình cho đến khi người dùng nhấn "OK". -For example: +Ví dụ: ```js run alert("Hello"); ``` -The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons etc, until they have dealt with the window. In this case -- until they press "OK". +Một cửa sổ nhỏ với dòng chữ `hello` xuất hiện, nó được gọi là *modal window*. Từ "modal" có nghĩa là người dùng không thể tương tác với các thành phần khác của trang web, vd như nhấn phím bất kỳ, cho đến khi click vào nút "OK". ## prompt -Function `prompt` accepts two arguments: +Hàm `prompt` có hai tham số: ```js no-beautify result = prompt(title[, default]); ``` -It shows a modal window with a text message, an input field for the visitor and buttons OK/CANCEL. +Nó cũng show một modal window với một tin nhắn và một input field để nhập liệu và nút OK/CANCEL. `title` -: The text to show to the visitor. +: Tin nhắn show lên có người dùng. `default` -: An optional second parameter, the initial value for the input field. +: tham số phụ, giá trị mặc định của input field. -The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing the CANCEL button or hitting the `key:Esc` key. +Người dùng gõ bất kỳ cái gì và nhấn OK. Hoặc thoát bằng nút CANCEL hoặc phím `key:Esc`. -The call to `prompt` returns the text from the field or `null` if the input was canceled. +Khi gọi `prompt` sẽ trả về text được nhập vào trong input form hoặc trả về `null` nếu bị canceled. -For instance: +Ví dụ: ```js run let age = prompt('How old are you?', 100); @@ -52,16 +50,16 @@ let age = prompt('How old are you?', 100); alert(`You are ${age} years old!`); // You are 100 years old! ``` -````warn header="IE: always supply a `default`" -The second parameter is optional. But if we don't supply it, Internet Explorer would insert the text `"undefined"` into the prompt. +````warn header="IE: Luôn luôn đặt giá trị `default`" +Tham số này là phụ, nhưng chúng ta nên gán giá trị cho nó vì nếu không Internet Explorer sẽ insert chuỗi `"undefined"`vào prompt. -Run this code in Internet Explorer to see that: +Chạy code này trên Internet Explorer để xem: ```js run let test = prompt("Test"); ``` -So, to look good in IE, it's recommended to always provide the second argument: +Do đó để ngọt hơn trên IE, cần bõ default vào: ```js run let test = prompt("Test", ''); // <-- for IE @@ -70,17 +68,17 @@ let test = prompt("Test", ''); // <-- for IE ## confirm -The syntax: +Cú pháp: ```js result = confirm(question); ``` -Function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL. +Hàm `confirm` show ra một modal window với `câu hỏi` và hai nút OK và CANCEL. -The result is `true` if OK is pressed and `false` otherwise. +Kết quả là `true` nếu click OK và `false` cho CANCEL. -For example: +Ví dụ: ```js run let isBoss = confirm("Are you the boss?"); @@ -88,24 +86,24 @@ let isBoss = confirm("Are you the boss?"); alert( isBoss ); // true if OK is pressed ``` -## Summary +## Tóm tắt -We covered 3 browser-specific functions to interact with the visitor: +Chúng ta đã học về 3 hàm đặc trưng của trình duyệt để tương tác với người dùng: `alert` -: shows a message. +: show một tin nhắn. `prompt` -: shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, all browsers return `null`. +: Hỏi người dùng nhập vào dữ liệu, nếu CANCEL hoặc `key:Esc` trình duyệt trả về `null`. `confirm` -: shows a message and waits for the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/`key:Esc`. +: Show một tin nhắn và đợi người dùng nhấn "OK" hoặc "CANCEL". returns `true` nếu nhấn OK và `false` nếu CANCEL/`key:Esc`. -All these methods are modal: they pause the script execution and don't allow the visitor to interact with the rest of the page until the message has been dismissed. +Tất cả 3 hàm trên đều là modal: Dừng lại sự thực thi của chương trình cho đến khi tin nhắn được xử lý xong. -There are two limitations shared by all the methods above: +Có hai sự giới hạn: -1. The exact location of the modal window is determined by the browser. Usually it's in the center. -2. The exact look of the window also depends on the browser. We can't modify it. +1. Vị trí của modal window do trình duyệt quyết định. thường là chính giữa màn hình. +2. Giao diện của modal windown do trình duyệt quyết định, chúng ta không sửa được. -That is the price for simplicity. There are other ways to show nicer windows and richer interaction with the visitor, but if "bells and whistles" do not matter much, these methods work just fine. +Đây là ba cách đơn giản nhất, còn nhiều cách tương tác với người dùng nữa, nhưng chỉ màu mè hơn chút thôi. Cơ bản dùng 3 thằng này là đủ rồi. From 6a941d9f47bd2a01fd56bf0e32b5f0989b2a2475 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 10 Oct 2017 11:07:14 +0700 Subject: [PATCH 30/78] Update article.md --- 1-js/02-first-steps/09-alert-prompt-confirm/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/article.md b/1-js/02-first-steps/09-alert-prompt-confirm/article.md index b3f3510ec4..9195f04fa5 100644 --- a/1-js/02-first-steps/09-alert-prompt-confirm/article.md +++ b/1-js/02-first-steps/09-alert-prompt-confirm/article.md @@ -1,4 +1,4 @@ -# Một số lệnh tương tác: alert, prompt, confirm +# Một số lệnh tương tác với user trên trình duyệt: alert, prompt, confirm Bài này chúng ta học về các hàm `alert`, `prompt` and `confirm`. From 0edbdd37fbabb396ea45cd5e1f2d00d87959ead1 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 10 Oct 2017 17:35:02 +0700 Subject: [PATCH 31/78] Update article.md --- 1-js/02-first-steps/10-ifelse/article.md | 92 ++++++++++++------------ 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/article.md b/1-js/02-first-steps/10-ifelse/article.md index 2fd4ca8853..4ea40ceb0b 100644 --- a/1-js/02-first-steps/10-ifelse/article.md +++ b/1-js/02-first-steps/10-ifelse/article.md @@ -1,16 +1,18 @@ -# Conditional operators: if, '?' +# Phép điều kiện: if, '?' -Sometimes we need to perform different actions based on a condition. +Ở đây mình dịch là *phép* điều kiện chứ không phải là biểu thức điều kiện, điều này có dụng ý là `?` vẫn là một operator như các phép toán mà chúng ta đã học ở bài trước. -There is the `if` statement for that and also the conditional (ternary) operator for conditional evaluation which we will be referring as the “question mark” operator: `"?"` for simplicity. +Thỉnh thoảng chúng ta cần thực thi các hành động khác nhau tùy thuộc vào kết quả của một biểu thức nào đó. + +Chúng ta dùng câu lệnh `if` cho các hành động phức tạp, hoặc phép điều kiện `"?"` cho các hành động đơn giản. [cut] -## The "if" statement +## Câu lệnh "if" -The "if" statement gets a condition, evaluates it and, if the result is `true`, executes the code. +Lệnh "if" nhận vào một biểu thức điều kiện, tính toán biểu thức đó, nếu kết quả là `true` thì thực hiện các hành động. -For example: +Ví dụ: ```js run let year = prompt('In which year was ECMAScript-2015 specification published?', ''); @@ -20,9 +22,9 @@ if (year == 2015) alert( 'You are right!' ); */!* ``` -In the example above, the condition is a simple equality check: `year == 2015`, but it can be much more complex. +Ở ví dụ trên, biểu thức điều kiện đơn giản là: `year == 2015`. -If there is more than one command to execute, we can use a code block in figure brackets: +Nếu có nhiều hành động được thực thi, ta viết chúng vào block (trong cặp dấu {} ): ```js if (year == 2015) { @@ -31,18 +33,18 @@ if (year == 2015) { } ``` -It is recommended to use figure brackets every time with `if`, even if there is only one command. That improves readability. +Nên dùng cặp ngoặc nhọn cho `if`, cho dù chỉ có một câu lệnh, như thế sẽ dễ đọc hơn. -## Boolean conversion +## Chuyển đổi Boolean -The `if (…)` statement evaluates the expression in parentheses and converts it to the boolean type. +Lệnh `if (…)` thực hiện biểu thức điều kiện trong cặp dấu ngoặc và convert kết quả sang kiểu boolean. -Let's recall the conversion rules from the chapter : +Xem lại các quy tắc ép kiểu ở chương : -- A number `0`, an empty string `""`, `null`, `undefined` and `NaN` become `false`. Because of that they are called "falsy" values. -- Other values become `true`, so they are called "truthy". +- Số `0`, chuỗi rỗng `""`, `null`, `undefined` và `NaN` sẽ chuyển đổi thành `false`. +- Giá trị khác chuyển đổi thành `true`. -So, the code under this condition would never execute: +Vì vậy code bên dưới sẽ không được thực thi: ```js if (0) { // 0 is falsy @@ -50,7 +52,7 @@ if (0) { // 0 is falsy } ``` -...And inside this condition -- always works: +...và ví dụ bên dưới, code được thực thi: ```js if (1) { // 1 is truthy @@ -58,7 +60,7 @@ if (1) { // 1 is truthy } ``` -We can also pass a pre-evaluated boolean value to `if`, like here: +Cũng có thể dùng một biểu thức được convert trước thành Boolean vào `if` : ```js let cond = (year == 2015); // equality evaluates to true or false @@ -68,11 +70,11 @@ if (cond) { } ``` -## The "else" clause +## Mệnh đề "else" -The `if` statement may contain an optional "else" block. It executes when the condition is wrong. +Lệnh `if` có thể chứa thêm mệnh đề "else" phía sau. Code trong `else block` sẽ được thực thi nếu biểu thức điều kiện là `false`. -For example: +Ví dụ: ```js run let year = prompt('In which year was ECMAScript-2015 specification published?', ''); @@ -83,11 +85,11 @@ if (year == 2015) { } ``` -## Several conditions: "else if" +## Sử dụng "else if" cho nhiều btđk -Sometimes we'd like to test several variants of a condition. There is an `else if` clause for that. +Khi có nhiều btđk chúng ta dùng mệnh đề `else if` . -For example: +VD: ```js run let year = prompt('In which year was ECMAScript-2015 specification published?', ''); @@ -101,15 +103,15 @@ if (year < 2015) { } ``` -In the code above JavaScript first checks `year < 2015`. If it is falsy it then goes to the next condition `year > 2015`, and otherwise shows the last `alert`. +Ở code trên, JavaScript đầu tiên sẽ kiểm tra btdk `year < 2015`. Nếu sai thì tiếp tục kiểm tra btđk `year > 2015`, nếu sai tiếp thì thực thi lệnh `alert`. -There can be more `else if` blocks. The ending `else` is optional. +Có thể có thêm nhiều `else if` . Và kết thúc là `else` (optional). -## Ternary operator '?' +## phép '?' -Sometimes we need to assign a variable depending on a condition. +Thỉnh thoảng chúng ta cần gán giá trị cho biến phụ thuộc vào điều kiện nào đó. -For instance: +Ví dụ: ```js run no-beautify let accessAllowed; @@ -126,24 +128,24 @@ if (age > 18) { alert(accessAllowed); ``` -The so-called "ternary" or "question mark" operator lets us do that shorter and simpler. +Chúng ta sẽ dùng `?` cho ví dụ trên, code sẽ ngắn và đơn giản hơn. -The operator is represented by a question mark `"?"`. The formal term "ternary" means that the operator has three operands. It is actually the one and only operator in JavaScript which has that many. +Phép toán `"?"` là phép toán duy nhất trong JS mà có 3 toán hạng. -The syntax is: +Cú pháp như sau: ```js let result = condition ? value1 : value2 ``` -The `condition` is evaluated, if it's truthy then `value1` is returned, otherwise -- `value2`. +Biểu thức điều kiện `condition` được kiểm tra, nếu đúng thì `value1` được trả về, ngược lại sẽ trả về `value2`. -For example: +Ví dụ: ```js let accessAllowed = (age > 18) ? true : false; ``` -Technically, we can omit parentheses around `age > 18`. The question mark operator has a low precedence. It executes after the comparison `>`, so that'll do the same: +Về mặt kỹ thuật chúng ta có thể bõ đi cặp dấu ngoặc bao `age > 18`. Phép `?` có độ ưu tiên khá thấp, do đó phép `>` sẽ được thực thi trước, vì vậy kết quả cuối cùng sẽ không thay đổi: ```js // the comparison operator "age > 18" executes first anyway @@ -151,10 +153,10 @@ Technically, we can omit parentheses around `age > 18`. The question mark operat let accessAllowed = age > 18 ? true : false; ``` -...But parentheses make the code more readable. So it's recommended to use them. +...Nhưng cặp dấu ngoặc làm code dễ đọc hơn. Do đó bạn nên sử dụng. ````smart -In the example above it's possible to evade the question mark operator, because the comparison by itself returns `true/false`: +Trong ví dụ trên có thể bõ đi `?` bởi vì phép so sánh cũng sẽ trả về giá trị `true/false`: ```js // the same @@ -162,11 +164,11 @@ let accessAllowed = age > 18; ``` ```` -## Multiple '?' +## Sử dụng nhiều phép '?' -A sequence of question mark `"?"` operators allows returning a value that depends on more than one condition. +Sử dụng nhiều phép `"?"` cho phép trả về giá trị phụ thuộc vào btđk. -For instance: +Ví dụ: ```js run let age = prompt('age?', 18); @@ -178,14 +180,14 @@ let message = (age < 3) ? 'Hi, baby!' : alert( message ); ``` -It may be difficult at first to grasp what's going on. But after a closer look we can see that it's just an ordinary sequence of tests. +Mới nhìn vào hơi khó hiểu. Nhìn kỹ và cố gắng hiểu thì bạn sẽ thấy thực ra chỉ là một chuỗi các bước kiểm tra mà thôi -1. The first question mark checks whether `age < 3`. -2. If true -- returns `'Hi, baby!'`, otherwise -- goes after the colon `":"` and checks for `age < 18`. -3. If that's true -- returns `'Hello!'`, otherwise -- goes after the next colon `":"` and checks for `age < 100`. -4. If that's true -- returns `'Greetings!'`, otherwise -- goes after the last colon `":"` and returns `'What an unusual age!'`. +1. Đầu tiên kiểm tra btđk `age < 3`. +2. Nếu true -- trả về `'Hi, baby!'`, trả về `age < 18`. Đây sẽ thực hiện tiếp kiểm tra biểu thức này +3. Nếu true -- trả về `'Hello!'`, ngược lại thì tiếp tục kiểm tra `age < 100`. +4. Nếu true -- trả về `'Greetings!'`, ngược lại thì trả về `'What an unusual age!'`. -The same logic using `if..else`: +Các bước trên cũng áp dụng tương tự đối với `if..else`: ```js if (age < 3) { From c5a3b76eaca92d60127ac0e770dc2f6682330c8d Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:20:22 +0700 Subject: [PATCH 32/78] Update article.md --- 1-js/02-first-steps/10-ifelse/article.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/article.md b/1-js/02-first-steps/10-ifelse/article.md index 4ea40ceb0b..c49f72045b 100644 --- a/1-js/02-first-steps/10-ifelse/article.md +++ b/1-js/02-first-steps/10-ifelse/article.md @@ -201,9 +201,9 @@ if (age < 3) { } ``` -## Non-traditional use of '?' +## Một số cách ít khi dùng của '?' -Sometimes the question mark `'?'` is used as a replacement for `if`: +Thỉnh thoảng `'?'` được dùng thay vì `if`: ```js run no-beautify let company = prompt('Which company created JavaScript?', ''); @@ -214,15 +214,15 @@ let company = prompt('Which company created JavaScript?', ''); */!* ``` -Depending on the condition `company == 'Netscape'`, either the first or the second part after `"?"` gets executed and shows the alert. +Phụ thuộc vào giá trị của btđk `company == 'Netscape'`, mà câu lệnh nào phía sau `"?"` sẽ được thực thi. -We don't assign a result to a variable here. The idea is to execute different code depending on the condition. +Chúng ta không gán giá trị ở đây. Ý tưởng là sẽ thực hiện một hành động nào đó phụ thuộc vào btđk. -**It is not recommended to use the question mark operator in this way.** +**Không khuyến khích sử dụng `"?"` theo cách này nhé.** -The notation seems to be shorter than `if`, which appeals to some programmers. But it is less readable. +Cách sử dụng này ngắn hơn dùng `if`, nhưng khó đọc. -Here is the same code with `if` for comparison: +Chuyển đổi thành `if` cho ví dụ trên: ```js run no-beautify let company = prompt('Which company created JavaScript?', ''); @@ -236,6 +236,6 @@ if (company == 'Netscape') { */!* ``` -Our eyes scan the code vertically. The constructs which span several lines are easier to understand than a long horizontal instruction set. +Mắt con người thường đọc code theo chiều dọc, vì thế code trên nhiều dòng sẽ dễ đọc hơn viết một dòng code dài. -The idea of a question mark `'?'` is to return one or another value depending on the condition. Please use it for exactly that. There is `if` to execute different branches of the code. +Ý tưởng khi dùng `'?'` là trả về một giá trị nào đó phụ thuộc vào btđk. Trong khi dùng `if` để thực thi các hành động nào đó phụ thuộc vào btđk. Các bạn chú ý sử dụng cho chính xác nhé. From 15c6d68a953e012e2062e3b229ca34e11bfa4282 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:22:32 +0700 Subject: [PATCH 33/78] Update task.md --- 1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md b/1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md index 5f16cda857..2fe5ed21f3 100644 --- a/1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md +++ b/1-js/02-first-steps/10-ifelse/1-if-zero-string/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# if (a string with zero) +# if ("0") -Will `alert` be shown? +Lênh `alert` có được thực thi hay không? ```js if ("0") { From 0096f29a5749bf8c45cebf30bf30f5591fc2e6c4 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:24:41 +0700 Subject: [PATCH 34/78] Update solution.md --- 1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md b/1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md index 51f1d46809..e30772c14d 100644 --- a/1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md +++ b/1-js/02-first-steps/10-ifelse/1-if-zero-string/solution.md @@ -1,8 +1,8 @@ -**Yes, it will.** +**Có. Lệnh `alert` sẽ được thực thi** -Any string except an empty one (and `"0"` is not empty) becomes `true` in the logical context. +Chỉ có chuỗi rỗng `""` mới trả về `false` còn lại chuỗi nào khác đều trả về `true` kể cả `"0"`. -We can run and check: +Bạn có thể chạy code để kiểm tra: ```js run if ("0") { From 0c0c7d3276c8a9c9993926d3883773d948a54869 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:44:10 +0700 Subject: [PATCH 35/78] Update task.md --- 1-js/02-first-steps/10-ifelse/2-check-standard/task.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/2-check-standard/task.md b/1-js/02-first-steps/10-ifelse/2-check-standard/task.md index 46fe05dc9b..19b592ff36 100644 --- a/1-js/02-first-steps/10-ifelse/2-check-standard/task.md +++ b/1-js/02-first-steps/10-ifelse/2-check-standard/task.md @@ -2,11 +2,11 @@ importance: 2 --- -# The name of JavaScript +# Tên của JavaScript -Using the `if..else` construct, write the code which asks: 'What is the "official" name of JavaScript?' +Sử dụng `if..else` Viết chương trình hỏi người dùng: 'What is the "official" name of JavaScript?' -If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!" +Nếu người dùng trả lời là "ECMAScript", show ra "Right!", ngược lại thì show ra: "Didn't know? ECMAScript!" ![](ifelse_task2.png) From ec08288e66e0671d08795cf8e7f10e2537207c97 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:51:26 +0700 Subject: [PATCH 36/78] Update task.md --- 1-js/02-first-steps/10-ifelse/3-sign/task.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/3-sign/task.md b/1-js/02-first-steps/10-ifelse/3-sign/task.md index 0c5d0e0084..b4e0078a05 100644 --- a/1-js/02-first-steps/10-ifelse/3-sign/task.md +++ b/1-js/02-first-steps/10-ifelse/3-sign/task.md @@ -4,12 +4,10 @@ importance: 2 # Show the sign -Using `if..else`, write the code which gets a number via `prompt` and then shows in `alert`: +Sử dụng `if..else`, viết chương trình nhập vào một số từ `prompt` và `alert`: -- `1`, if the value is greater than zero, -- `-1`, if less than zero, -- `0`, if equals zero. - -In this task we assume that the input is always a number. +- `1`, nếu số lớn hơn 0, +- `-1`, nếu số nhỏ hơn, +- `0`, nếu bằng 0. [demo src="if_sign"] From 31ea976d61a1d6cc31fa6cdca22df3dfdaf049b8 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:53:22 +0700 Subject: [PATCH 37/78] Update task.md --- 1-js/02-first-steps/10-ifelse/3-sign/task.md | 1 + 1 file changed, 1 insertion(+) diff --git a/1-js/02-first-steps/10-ifelse/3-sign/task.md b/1-js/02-first-steps/10-ifelse/3-sign/task.md index b4e0078a05..f608f7180c 100644 --- a/1-js/02-first-steps/10-ifelse/3-sign/task.md +++ b/1-js/02-first-steps/10-ifelse/3-sign/task.md @@ -10,4 +10,5 @@ Sử dụng `if..else`, viết chương trình nhập vào một số từ `prom - `-1`, nếu số nhỏ hơn, - `0`, nếu bằng 0. +Giả sử rằng người dùng luôn nhập vào "số". [demo src="if_sign"] From 8b12531d605fb595b1588f9cfc63d68c1e5d8b48 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 09:57:10 +0700 Subject: [PATCH 38/78] Update task.md --- .../02-first-steps/10-ifelse/4-check-login/task.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/4-check-login/task.md b/1-js/02-first-steps/10-ifelse/4-check-login/task.md index 4b371a1db6..dd6db3e640 100644 --- a/1-js/02-first-steps/10-ifelse/4-check-login/task.md +++ b/1-js/02-first-steps/10-ifelse/4-check-login/task.md @@ -4,17 +4,17 @@ importance: 3 # Check the login -Write the code which asks for a login with `prompt`. +Viết chương trình hỏi người dùng login từ `prompt`. -If the visitor enters `"Admin"`, then `prompt` for a password, if the input is an empty line or `key:Esc` -- show "Canceled.", if it's another string -- then show "I don't know you". +Nếu người dùng nhập vào `"Admin"`, thì `prompt` tiếp password, nếu nhập vào trống hoặc nhấn `key:Esc` -- thì show ra "Canceled.", nếu nhập vào sai pass thì show ra "I don't know you". -The password is checked as follows: +Kiểm tra password như sau: -- If it equals "TheMaster", then show "Welcome!", -- Another string -- show "Wrong password", -- For an empty string or cancelled input, show "Canceled." +- Nếu là "TheMaster", thì show ra "Welcome!", +- Chuỗi khác thì show ra "Wrong password", +- Không nhập vào hoặc nhấn phím `key:Esc` thì show ra "Canceled." -The schema: +Sơ đồ như sau: ![](ifelse_task.png) From 23b21d8bac09a39271100815acb4031acab035b8 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 10:07:19 +0700 Subject: [PATCH 39/78] Update task.md --- 1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md b/1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md index 684e239f2f..310759a5b0 100644 --- a/1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md +++ b/1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md @@ -2,9 +2,9 @@ importance: 5 --- -# Rewrite 'if' into '?' +# Thay 'if' bằng '?' -Rewrite this `if` using the ternary operator `'?'`: +Viết lại chương trình dùng `if` bên dưới bằng cách sử dụng phép `'?'`: ```js if (a + b < 4) { From a6be16c03e62c60dff86d50250f9f77fc53beda2 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 10:10:11 +0700 Subject: [PATCH 40/78] Update task.md --- .../10-ifelse/6-rewrite-if-else-question/task.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md b/1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md index 4f7d994a21..f418e567c4 100644 --- a/1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md +++ b/1-js/02-first-steps/10-ifelse/6-rewrite-if-else-question/task.md @@ -2,11 +2,11 @@ importance: 5 --- -# Rewrite 'if..else' into '?' +# Thay 'if..else' bằng '?' -Rewrite `if..else` using multiple ternary operators `'?'`. +Viết lại `if..else` bằng cách sử dụng các phép `'?'`. -For readability, it's recommended to split the code into multiple lines. +Để cho dễ đọc, hãy viết trên nhiều dòng. ```js let message; From b587d048f2c304393fbe56084e92e09252dc0335 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 15:29:00 +0700 Subject: [PATCH 41/78] Update article.md --- .../11-logical-operators/article.md | 146 +++++++++--------- 1 file changed, 71 insertions(+), 75 deletions(-) diff --git a/1-js/02-first-steps/11-logical-operators/article.md b/1-js/02-first-steps/11-logical-operators/article.md index b3aecc3119..3fb512b859 100644 --- a/1-js/02-first-steps/11-logical-operators/article.md +++ b/1-js/02-first-steps/11-logical-operators/article.md @@ -1,26 +1,24 @@ -# Logical operators +# Các phép logic -There are three logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT). +Có ba phép logic trong JavaScript: `||` (OR), `&&` (AND), `!` (NOT). -Although they are called "logical", they can be applied to values of any type, not only boolean. The result can also be of any type. - -Let's see the details. +Mặc dù được gọi là "logic", nhưng có thể dùng trên bất cứ kiểu dữ liệu nào không riêng gì Boolean. Kết quả trả về cũng có thể là bất cứ kiểu dữ liệu nào. [cut] ## || (OR) -The "OR" operator is represented with two vertical line symbols: +Phép hoặc "OR" được thể hiện bằng hai dấu gạch thẳng đứng như bên dưới: ```js result = a || b; ``` -In classical programming, logical OR is meant to manipulate boolean values only. If any of its arguments are `true`, then it returns `true`, otherwise it returns `false`. +Trong lập trình cổ điển, phép OR chỉ sử dụng trên kiểu Boolean. nếu có bất cứ tham số nào có giá trị là `true`, thì trả về `true`, ngược lại trả về `false`. -In JavaScript the operator is a little bit more tricky and powerful. But first let's see what happens with boolean values. +Trong JavaScript phép OR có chút khác biệt và mạnh mẽ hơn. Nhưng trước hết ta tìm hiểu OR sử dụng trên Boolean. -There are four possible logical combinations: +Có bốn khả năng như bên dưới: ```js run alert( true || true ); // true @@ -29,11 +27,11 @@ alert( true || false ); // true alert( false || false ); // false ``` -As we can see, the result is always `true` except for the case when both operands are `false`. +Giá trị trả về là `true` trừ trường hợp tất cả toán hạng đều là `false`. -If an operand is not boolean, then it's converted to boolean for the evaluation. +Nếu có toán hạng không phải kiểu Boolean, nó sẽ được chuyển đổi thành Boolean. -For instance, a number `1` is treated as `true`, a number `0` -- as `false`: +Ví dụ number `1` chuyển thành `true`, và number `0` -- là `false`: ```js run if (1 || 0) { // works just like if( true || false ) @@ -41,9 +39,9 @@ if (1 || 0) { // works just like if( true || false ) } ``` -Most of the time, OR `||` is used in an `if` statement to test if *any* of the given conditions is correct. +Hầu hết trường hợp, OR `||` được sử dụng cùng câu lệnh `if` để kiểm tra có có giá trị nào là `true` hay không. -For example: +Ví dụ: ```js run let hour = 9; @@ -55,7 +53,7 @@ if (hour < 10 || hour > 18) { } ``` -We can pass more conditions: +Chúng ta có thể sử dụng nhiều btđk hơn: ```js run let hour = 12; @@ -66,29 +64,28 @@ if (hour < 10 || hour > 18 || isWeekend) { } ``` -## OR seeks the first truthy value - -The logic described above is somewhat classical. Now let's bring in the "extra" features of JavaScipt. +## OR tìm kiếm giá trị true đầu tiên -The extended algorithm works as follows. +Đây là điểm khác biệt giữa JavaScipt và lập trình cổ điển đã nói ở trên. -Given multiple OR'ed values: +Sự khác biệt như sau: ```js result = value1 || value2 || value3; ``` -The OR `"||"` operator does the following: +Phép OR `"||"` sẽ được thực hiện như sau: -- Evaluate operands from left to right. -- For each operand, convert it to boolean. If the result is `true`, then stop and return the original value of that operand. -- If all other operands have been assessed (i.e. all were `falsy`), return the last operand. +- Đánh giá các toán hạng từ trái sang phải. +- Chuyển đổi từng toán hạng sang kiểu Boolean. Nếu thấy có toán hạng là `true`, phép toán kết thúc, trả về giá trị nguyên bản khi chưa chuyển đổi (orginal value) của toán hạng đó. +- Nếu tất cả toán hạng đều là `false` thì trả về toán hạng cuối cùng. -A value is returned in its original form, without the conversion. +Nói cách khác phép OR `"||"` trả về giá trị `truthy` đầu tiên. Hoặc trả về giá trị cuối cùng nếu tất cả toán hạng là `falsy`. +Nhắc lại một chút: +- `truthy` ám chỉ các giá trị mà khi convert sang Boolean thì sẽ được `true`. Ví dụ như 1, "fdsfsf", "0",... +- `falsy` ám chỉ các giá trị mà khi convert sang Boolean thì sẽ được `fasle`. Ví dụ như null, 0, "", .... -In other words, a chain of OR `"||"` returns the first truthy value or the last one if no such value is found. - -For instance: +Ví dụ: ```js run alert( 1 || 0 ); // 1 (1 is truthy) @@ -99,13 +96,11 @@ alert( null || 0 || 1 ); // 1 (the first truthy value) alert( undefined || null || 0 ); // 0 (all falsy, returns the last value) ``` -That leads to some interesting usages compared to a "pure, classical, boolean-only OR". - -1. **Getting the first truthy value from the list of variables or expressions.** +1. **Lấy giá trị truthy từ các toán hạng hoặc biểu thức.** - Imagine we have several variables, which can either contain the data or be `null/undefined`. And we need to choose the first one with data. + Tưởng tượng bạn có nhiều biến, và các biến này có thể có giá trị là `null/undefined`. Và chúng ta cần chọn biến đầu tiên có giá trị mà ta cần. - We can use OR `||` for that: + Chúng ta sử dụng phép `||` : ```js run let currentUser = null; @@ -118,14 +113,15 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on alert( name ); // selects "John" – the first truthy value ``` - If both `currentUser` and `defaultUser` were falsy then `"unnamed"` would be the result. -2. **Short-circuit evaluation.** + Nếu cả `currentUser` và `defaultUser` là falsy thì giá trị `"unnamed"` sẽ là kết quả. +2. **đánh giá ngắn mạch** - Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The evaluation stops when a truthy value is reached, and the value is returned. The process is called "a short-circuit evaluation", because it goes as short as possible from left to right. + Toán hạng có thể là các giá trị, cũng có thể là các biểu thức trừu tượng. OR sẽ đánh giá chúng từ trái sang phải. Sự đánh giá này sẽ dừng lại khi thấy giá trị truthy đầu tiên, và giá trị đó sẽ được trả về. Quá trình này gọi là đánh giá ngắn mạch "a short-circuit evaluation", bởi vì sự đánh giá này là ngắn nhất có thể từ trái sang phải. + "Ngắn mạch" từ này hay dùng trong ngành điện. Các bạn có thể google xem nhé. - This is clearly seen when the expression given as the second argument has a side effect. Like a variable assignment. + Điều này được thấy rõ khi biểu thức được đưa ra như là đối số thứ hai có tác dụng phụ. Giống như một phép gán biến. - If we run the example below, `x` would not get assigned: + Chạy đoạn code sau, ta sẽ thấy `x` không được gán giá trị: ```js run no-beautify let x; @@ -135,7 +131,7 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on alert(x); // undefined, because (x = 1) not evaluated ``` - ...And if the first argument is `false`, then `OR` goes on and evaluates the second one thus running the assignment: + ...và nếu toán hạng đầu tiên là `false`, sau đó `OR` đánh giá toán hạng thứ hai, chính là biểu thức `(x = 1)`, và `x` sẽ được gán giá trị.: ```js run no-beautify let x; @@ -145,21 +141,21 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on alert(x); // 1 ``` - An assignment is a simple case, other side effects can be involved. + Phép gán ở trên chỉ là một ví dụ đơn giản, ta còn có thể dùng nhiều biểu thức phức tạp hơn. - As we can see, such a use case is a "shorter way to do `if`". The first operand is converted to boolean and if it's false then the second one is evaluated. + Như bạn thấy hầu hết các trường hợp đều "ngắn hơn là dùng `if`". - Most of time it's better to use a "regular" `if` to keep the code easy to understand, but sometimes that can be handy. + Nói chung là tùy trường hợp dùng OR cho ngắn hay dùng `if` để code dễ hiểu hơn là tùy ở bạn. ## && (AND) -The AND operator is represented with two ampersands `&&`: +Phép AND thể hiện bằng hai dấu và `&&`: ```js result = a && b; ``` -In classical programming AND returns `true` if both operands are truthy and `false` otherwise: +Trong lập trình cổ điển phép AND trả về `true` nếu cả hai toán hạng là truthy và trả về `false` nếu ngược lại: ```js run alert( true && true ); // true @@ -168,7 +164,7 @@ alert( true && false ); // false alert( false && false ); // false ``` -An example with `if`: +Ví dụ với `if`: ```js run let hour = 12; @@ -179,7 +175,7 @@ if (hour == 12 && minute == 30) { } ``` -Just as for OR, any value is allowed as an operand of AND: +tương tự OR, AND có thể dùng trên bất kỳ kiểu dữ liệu nào: ```js run if (1 && 0) { // evaluated as true && false @@ -188,25 +184,25 @@ if (1 && 0) { // evaluated as true && false ``` -## AND seeks the first falsy value +## AND tìm giá trị falsy đầu tiên -Given multiple AND'ed values: +Xem ví dụ: ```js result = value1 && value2 && value3; ``` -The AND `"&&"` operator does the following: +Phép AND `"&&"` sẽ thực hiện như sau: -- Evaluate operands from left to right. -- For each operand, convert it to a boolean. If the result is `false`, stop and return the original value of that operand. -- If all other operands have been assessed (i.e. all were truthy), return the last operand. +- Đánh giá các toán hạng từ trái sang phải. +- Chuyển đổi từng toán hạng sang Boolean. Nếu gặp giá trị `false`, kết thúc phép toán và trả về orginal value của toán hạng đó. +- Nếu tất cả toán hạng là truthy, trả về toán hạng cuối cùng. -In other words, AND returns the first falsy value or the last value if none were found. +Nói cách khác, AND trả về giá trị falsy đầu tiên. Hoặc trả về toán hạng cuối cùng nếu tất cả toán hạng đều là truthy -The rules above are similar to OR. The difference is that AND returns the first *falsy* value while OR returns the first *truthy* one. +Quy tắc này tương tự OR. Khác biệt là AND trả về giá trị *falsy* đầu tiên trong khi OR trả về giá trị *truthy* đầu tiên. -Examples: +Ví dụ: ```js run // if the first operand is truthy, @@ -220,31 +216,31 @@ alert( null && 5 ); // null alert( 0 && "no matter what" ); // 0 ``` -We can also pass several values in a row. See how the first falsy one is returned: +Giá trị falsy đầu tiên được trả về: ```js run alert( 1 && 2 && null && 3 ); // null ``` -When all values are truthy, the last value is returned: +Nếu tất cả là truthy, giá trị cuối cùng được trả về: ```js run alert( 1 && 2 && 3 ); // 3, the last one ``` -````smart header="AND `&&` executes before OR `||`" -The precedence of the AND `&&` operator is higher than OR `||`, so it executes before OR. +````smart header="AND `&&` được thực thi trước OR `||`" +Phép AND `&&` có độ ưu tiên cao hơn phép OR `||`. -In the code below `1 && 0` is calculated first: +Xem vd bên dưới `1 && 0` sẽ được thực thi trước: ```js run alert( 5 || 1 && 0 ); // 5 ``` ```` -Just like OR, the AND `&&` operator can sometimes replace `if`. +Tương tự OR, Phép AND `&&` thỉnh thoảng được dùng để thay thế `if`. -For instance: +Ví dụ: ```js run let x = 1; @@ -252,9 +248,9 @@ let x = 1; (x > 0) && alert( 'Greater than zero!' ); ``` -The action in the right part of `&&` would execute only if the evaluation reaches it. That is: only if `(x > 0)` is true. +Hành động phía sau `&&` chỉ được thực thi nếu `(x > 0)` là đúng. -So we basically have an analogue for: +Nó tương đương với: ```js run let x = 1; @@ -264,42 +260,42 @@ if (x > 0) { } ``` -The variant with `&&` appears to be shorter. But `if` is more obvious and tends to be a little bit more readable. +Dùng `&&` thấy ngắn hơn dùng `if`. Nhưng dùng `if` rõ ràng và dễ đọc hơn. -So it is recommended to use every construct for its purpose. Use `if` if we want if. And use `&&` if we want AND. +Cho nên hãy sử dụng cho đúng mục đích. ## ! (NOT) -The boolean NOT operator is represented with an exclamation sign `"!"`. +Phép phủ định NOT được thể hiện bằn dấu chấm than `"!"`. -The syntax is pretty simple: +Cấu trúc ngữ pháp khá đơn giản: ```js result = !value; ``` -The operator accepts a single argument and does the following: +Nó là phép toán một ngôi có nguyên tắc đơn giản như sau: -1. Converts the operand to boolean type: `true/false`. -2. Returns an inverse value. +1. Chuyển đổi toán hạng thành Boolean: `true/false`. +2. Trả về giá trị ngược lại. -For instance: +Ví dụ: ```js run alert( !true ); // false alert( !0 ); // true ``` -A double NOT `!!` is sometimes used for converting a value to boolean type: +Sử dụng hai lần phép NOT `!!` thỉnh thoảng được sử dụng để convert giá trị thành Boolean: ```js run alert( !!"non-empty string" ); // true alert( !!null ); // false ``` -That is, the first NOT converts the value to boolean and returns the inverse, and the second NOT inverses it again. At the end we have a plain value-to-boolean conversion. +Vì phủ định của phủ định là khẳng định mà. -There's a little more verbose way to do the same thing -- a built-in `Boolean` function: +Có cách đơn giản hơn là sử dụng hàm `Boolean` có sẵn trong JS: ```js run alert( Boolean("non-empty string") ); // true From edfff9596a7b9511f15e0655b2576c617731044a Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 16:45:04 +0700 Subject: [PATCH 42/78] Update article.md --- 1-js/02-first-steps/12-while-for/article.md | 27 ++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/1-js/02-first-steps/12-while-for/article.md b/1-js/02-first-steps/12-while-for/article.md index a75137ee65..753495a04e 100644 --- a/1-js/02-first-steps/12-while-for/article.md +++ b/1-js/02-first-steps/12-while-for/article.md @@ -1,16 +1,16 @@ -# Loops: while and for +# Vòng lặp: while và for -We often have a need to perform similar actions many times in a row. +Thỉnh thoảng chúng ta cần lặp lại các hành động tương tự nhiều lần. -For example, when we need to output goods from a list one after another. Or just run the same code for each number from 1 to 10. +Ví dụ in ra tên hàng trong một list các mặt hàng, hay in ra các số từ 1 đên 100. -*Loops* are a way to repeat the same part of code multiple times. +*Loops* - Vòng lặp được sử dụng để thực hiện các công việc này. [cut] -## The "while" loop +## Vòng lặp "while" -The `while` loop has the following syntax: +Cú pháp: ```js while (condition) { @@ -19,9 +19,9 @@ while (condition) { } ``` -While the `condition` is `true`, the `code` from the loop body is executed. +Khi `condition` là `true`, thì `code` trong phần thân của vòng lặp sẽ được thực thi. -For instance, the loop below outputs `i` while `i < 3`: +Ví dụ, in ra `i` khi `i < 3`: ```js run let i = 0; @@ -31,13 +31,13 @@ while (i < 3) { // shows 0, then 1, then 2 } ``` -A single execution of the loop body is called *an iteration*. The loop in the example above makes three iterations. +Một lần thực thi code trong phần thân vòng lặp được gọi là *an iteration*. Vòng lặp trong ví dụ trên có 3 iterations. -If there were no `i++` in the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and for server-side JavaScript we can kill the process. +Nếu không có lệnh `i++` trong ví dụ trên, vòng lặp sẽ lặp (theo lý thuyết) mãi mãi. Trong thực tế trình duyệt sẽ có cách để stop những vòng lặp mãi mãi, và nếu code ở phần JavaScript-server-side chúng ta có thể chấm dứt tiến trình (kill the process). -Any expression or a variable can be a loop condition, not just a comparison. They are evaluated and converted to boolean by `while`. +Không chỉ riêng biểu thức so sánh, một biểu thức bất kỳ hay một giá trị có thể là btđk của vòng lặp. Chúng sẽ được đánh giá và convert sang boolean bởi `while`. -For instance, the shorter way to write `while (i != 0)` could be `while (i)`: +Ví dụ cách viết ngắn hơn cho `while (i != 0)` là `while (i)`: ```js run let i = 3; @@ -49,8 +49,7 @@ while (i) { // when i becomes 0, the condition becomes falsy, and the loop stops } ``` -````smart header="Brackets are not required for a single-line body" -If the loop body has a single statement, we can omit the brackets `{…}`: +````smart header="Có thể bõ cặp `{…}` ngoặc nếu chỉ có một lệnh trong thân" ```js run let i = 3; From e3d343eba4d2f7ba5e1e915578755746ade8e912 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 12 Oct 2017 18:11:39 +0700 Subject: [PATCH 43/78] Update article.md --- 1-js/02-first-steps/12-while-for/article.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/12-while-for/article.md b/1-js/02-first-steps/12-while-for/article.md index 753495a04e..3c5ca8c539 100644 --- a/1-js/02-first-steps/12-while-for/article.md +++ b/1-js/02-first-steps/12-while-for/article.md @@ -59,9 +59,9 @@ while (i) alert(i--); ``` ```` -## The "do..while" loop +## Vòng lặp "do..while" -The condition check can be moved *below* the loop body using the `do..while` syntax: +Btđk nằm phía *dưới* phần thân của vòng lặp `do..while`, cú pháp: ```js do { @@ -69,7 +69,7 @@ do { } while (condition); ``` -The loop will first execute the body, then check the condition and, while it's truthy, execute it again and again. +Vòng lặp thực thi code trong phần thân trước, sau đó kiểm tra btđk nếu là truthy, thực hiện code một lần nữa. For example: From f4e44ef3b08eb88872167a6f66b3d39a4902e939 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 13 Oct 2017 10:40:55 +0700 Subject: [PATCH 44/78] Update article.md --- 1-js/02-first-steps/12-while-for/article.md | 137 ++++++++++---------- 1 file changed, 66 insertions(+), 71 deletions(-) diff --git a/1-js/02-first-steps/12-while-for/article.md b/1-js/02-first-steps/12-while-for/article.md index 3c5ca8c539..2039ffdd03 100644 --- a/1-js/02-first-steps/12-while-for/article.md +++ b/1-js/02-first-steps/12-while-for/article.md @@ -69,9 +69,9 @@ do { } while (condition); ``` -Vòng lặp thực thi code trong phần thân trước, sau đó kiểm tra btđk nếu là truthy, thực hiện code một lần nữa. +Vòng lặp thực thi code trong phần thân trước, sau đó kiểm tra đk nếu là truthy, thực hiện code một lần nữa. -For example: +Ví dụ: ```js run let i = 0; @@ -81,13 +81,13 @@ do { } while (i < 3); ``` -This form of syntax is rarely used except when you want the body of the loop to execute **at least once** regardless of the condition being truthy. Usually, the other form is preferred: `while(…) {…}`. +Cú pháp này ít khi được sử dụng trừ khi bạn muốn phần body được thực thi **ít nhất 1 lần** bất kể btđk là truthy. Thông thường thì `while(…) {…}` hay được dùng hơn. -## The "for" loop +## Vòng lặp "for" -The `for` loop is the most often used one. +Vòng lặp `for` là vòng lặp hay được sử dụng nhất. -It looks like this: +Cú pháp: ```js for (begin; condition; step) { @@ -95,7 +95,7 @@ for (begin; condition; step) { } ``` -Let's learn the meaning of these parts by example. The loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`: +Chúng ta sẽ học về 3 thành phần của `for` qua các ví dụ. Ví dụ bên dưới lệnh `alert(i)` được thực thi với `i` chạy từ `0` đến (nhưng ko bao gồm) `3`: ```js run for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2 @@ -103,17 +103,17 @@ for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2 } ``` -Let's examine the `for` statement part by part: +Chúng ta cùng xem xét `for` theo từng phần: | part | | | |-------|----------|----------------------------------------------------------------------------| -| begin | `i = 0` | Executes once upon entering the loop. | -| condition | `i < 3`| Checked before every loop iteration, if fails the loop stops. | -| step| `i++` | Executes after the body on each iteration, but before the condition check. | -| body | `alert(i)`| Runs again and again while the condition is truthy | +| begin | `i = 0` | Thực hiện một lần khi bước vào vòng lặp. | +| condition | `i < 3`| Kiểm tra trước khi thực thi iteration, Nếu `false` thì dừng vòng lặp. | +| step| `i++` | Thực thi sau mỗi iteration, nhưng trước khi kiểm tra đk. | +| body | `alert(i)`| chạy lặp đi lặp lại nếu đk là truthy | -The general loop algorithm works like this: +Thuật toán của vòng lặp hoạt động như thế này: ``` Run begin → (if condition → run body and run step) @@ -122,9 +122,8 @@ Run begin → ... ``` -If you are new to loops, then maybe it would help if you go back to the example and reproduce how it runs step-by-step on a piece of paper. -Here's what exactly happens in our case: +Đối với ví dụ trên: ```js // for (let i = 0; i < 3; i++) alert(i) @@ -140,8 +139,8 @@ if (i < 3) { alert(i); i++ } // ...finish, because now i == 3 ``` -````smart header="Inline variable declaration" -Here the "counter" variable `i` is declared right in the loop. That's called an "inline" variable declaration. Such variables are visible only inside the loop. +````smart header="khai báo biến inline" +Biến `i` được khai báo trong vòng loop. Đó được gọi là khai báo biến "inline". Những biến này chỉ sử dụng được trong vòng lặp. ```js run for (*!*let*/!* i = 0; i < 3; i++) { @@ -150,7 +149,7 @@ for (*!*let*/!* i = 0; i < 3; i++) { alert(i); // error, no such variable ``` -Instead of defining a variable, we can use an existing one: +Thay vì khai báo biến, cũng có thể sử dụng biến có sẵn: ```js run let i = 0; @@ -165,11 +164,11 @@ alert(i); // 3, visible, because declared outside of the loop ```` -### Skipping parts +### Lược bỏ thành phần -Any part of `for` can be skipped. +Có thể lược bỏ bất cứ thành phần nào của `for`. -For example, we can omit `begin` if we don't need to do anything at the loop start. +Ví dụ chúng ta lược bỏ `begin` nếu không cần giá trị khởi tạo. Like here: @@ -181,7 +180,7 @@ for (; i < 3; i++) { // no need for "begin" } ``` -We can also remove the `step` part: +Lược bõ `step`: ```js run let i = 0; @@ -191,9 +190,9 @@ for (; i < 3;) { } ``` -The loop became identical to `while (i < 3)`. +Vòng lặp trên giống như `while (i < 3)`. -We can actually remove everything, thus creating an infinite loop: +Có thể lược bỏ tất cả để tạo ra một vòng lặp vô hạn: ```js for (;;) { @@ -201,15 +200,15 @@ for (;;) { } ``` -Please note that the two `for` semicolons `;` must be present, otherwise it would be a syntax error. +Chú ý trong `for` dùng 2 dấu `;` nếu không sẽ báo lỗi cú pháp. -## Breaking the loop +## Thoát vòng lặp -Normally the loop exits when the condition becomes falsy. +Bình thường thì vòng lặp kết thúc khi đk là falsy. -But we can force the exit at any moment. There's a special `break` directive for that. +Nhưng chúng ta cũng có thể dừng vòng lặp bất cứ khi nào bằng một chỉ thị đặc biệt có tên là `break`. -For example, the loop below asks the user for a series of numbers, but "breaks" when no number is entered: +Ví dụ vòng lặp hỏi người dùng nhập vào một dãy số, và sẽ thoát nếu không có số nào được nhập vào: ```js let sum = 0; @@ -228,17 +227,15 @@ while (true) { alert( 'Sum: ' + sum ); ``` -The `break` directive is activated in the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing the control to the first line after the loop. Namely, `alert`. - -The combination "infinite loop + `break` as needed" is great for situations when the condition must be checked not in the beginning/end of the loop, but in the middle, or even in several places of the body. +Chỉ thị `break` được chạy ở dòng `(*)` nếu user nhập vào dòng trống hoặc nhấn cancel. Nó dừng vòng lặp ngay lập tức, và đưa chương trình đến dòng code tiếp theo sau vòng lặp. `alert`. -## Continue to the next iteration [#continue] +Sự kết hợp của "infinite loop" và `break` hay dùng cho các trường hợp đk ko phải được kiểm tra ở đầu hay cuối vòng lặp, mà ở giữa vòng lặp hay bất cứ đâu trong body. -The `continue` directive is a "lighter version" of `break`. It doesn't stop the whole loop. Instead it stops the current iteration and forces the loop to start a new one (if the condition allows). +## Chỉ thị Continue [#continue] -We can use it if we're done on the current iteration and would like to move on to the next. +Chỉ thị `continue` dừng lại iteration hiện thời và chuyển vòng lặp đến lần lặp mới . -The loop above uses `continue` to output only odd values: +Sử dụng `continue` để in ra các số lẽ: ```js run no-beautify for (let i = 0; i < 10; i++) { @@ -250,10 +247,10 @@ for (let i = 0; i < 10; i++) { } ``` -For even values of `i` the `continue` directive stops body execution, passing the control to the next iteration of `for` (with the next number). So the `alert` is only called for odd values. +Với giá trị `i` chẵn, chỉ thị `continue` dừng sự thực thi trong body, chuyển vòng lặp qua iteration tiếp theo. Cho nên lệnh `alert` chỉ được gọi cho các giá trị lẽ. -````smart header="The directive `continue` helps to decrease nesting level" -A loop that shows odd values could look like this: +````smart header="Chỉ thị `continue` giảm việc nesting trong code" +Vòng lặp trên có thể viết: ```js for (let i = 0; i < 10; i++) { @@ -265,15 +262,15 @@ for (let i = 0; i < 10; i++) { } ``` -From a technical point of view it's identical to the example above. Surely, we can just wrap the code in the `if` block instead of `continue`. +Hai cách dùng ở trên là tương đương nhau. -But as a side-effect we got one more figure brackets nesting level. If the code inside `if` is longer than a few lines, that may decrease the overall readability. +Nhưng nếu mã code trong `if` nhiều hơn thì code của ta sẽ khó đọc hơn vì nó thụt vào. ```` -````warn header="No `break/continue` to the right side of '?'" -Please note that syntax constructs that are not expressions cannot be used in `'?'`. In particular, directives `break/continue` are disallowed there. +````warn header="Không dùng `break/continue` bên phải '?'" +Không được dùng trong biểu thức với `'?'`. Chỉ thị `break/continue` không được chấp nhận ở đây. -For example, if we take this code: +Ví dụ ta có code: ```js if (i > 5) { @@ -283,24 +280,24 @@ if (i > 5) { } ``` -...And rewrite it using a question mark: +...Và viết lại với `?`: ```js no-beautify (i > 5) ? alert(i) : *!*continue*/!*; // continue not allowed here ``` -...Then it stops working. The code like this will give a syntax error: +...sẽ không chạy được. Code sẽ báo lỗi cú pháp: -That's just another reason not to use a question mark operator `'?'` instead of `if`. +Đây là lý do đừng sử dụng `'?'` thay cho `if`. ```` -## Labels for break/continue +## Đánh nhãn cho break/continue -Sometimes we need to break out from multiple nested loops at once. +Thỉnh thoảng ta muốn break vòng lặp nào đó trong nhiều vòng lặp chồng nhau. -For example, in the code below we loop over `i` and `j` prompting for coordinates `(i, j)` from `(0,0)` to `(3,3)`: +Ví du hai vòng lặp chồng nhau `i` và `j`: ```js run no-beautify for (let i = 0; i < 3; i++) { @@ -317,20 +314,20 @@ for (let i = 0; i < 3; i++) { alert('Done!'); ``` -We need a way to stop the process if the user cancels the input. +Chúng ta cần stop vòng lặp nếu user nhấn cancels hoặc không nhập vào gì cả. -The ordinary `break` after `input` would only break the inner loop. That's not sufficient. Labels come to the rescue. +Nếu dùng `break` sau `input` chỉ thoát được vòng lặp chứa nó. Chứ không thoát cả 2 vòng lặp. Sử dụng *label* để giải quyết vấn đề này. -A *label* is an identifier with a colon before a loop: +Một nhã *label* là một cái tên đặt cho vòng lặp, cú pháp: ```js labelName: for (...) { ... } ``` -The `break ` statement in the loop breaks out to the label. +Chỉ thị `break ` thoát khỏi vòng lặp có tên là labelName. -Like here: +Như thế này: ```js run no-beautify *!*outer:*/!* for (let i = 0; i < 3; i++) { @@ -348,42 +345,40 @@ Like here: alert('Done!'); ``` -In the code above `break outer` looks upwards for the label named `outer` and breaks out of that loop. +Ở ví dụ trên `break outer` tìm vòng lặp nào có tên là `outer` và thoát khỏi nó. -So the control goes straight from `(*)` to `alert('Done!')`. +và chương trình nhảy từ `(*)` sang `alert('Done!')`. -We can also move the label onto a separate line: +Có thể viết ra các dòng như này: ```js no-beautify outer: for (let i = 0; i < 3; i++) { ... } ``` -The `continue` directive can also be used with a label. In this case the execution jumps to the next iteration of the labeled loop. +Chỉ thị `continue` cũng có thể dùng với label. -````warn header="Labels are not a \"goto\"" -Labels do not allow us to jump into an arbitrary place of code. +Chỉ thị `break/continue` chỉ hoạt động được trong loops. -For example, it is impossible to do this: +Ví dụ như thế này sẽ báo lỗi: ```js break label; // jumps to label? No. label: for (...) ``` -The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive. ```` -## Summary +## Tóm tắt -We covered 3 types of loops: +Chúng ta đã học 3 loại vòng lặp: -- `while` -- The condition is checked before each iteration. -- `do..while` -- The condition is checked after each iteration. -- `for (;;)` -- The condition is checked before each iteration, additional settings available. +- `while` -- đk được kiểm tra trước mỗi iteration. +- `do..while` -- đk được kiểm tra sau mỗi iteration. +- `for (;;)` -- đk được kiểm tra trước mỗi iteration, có thêm phần step settings sau mỗi iteration. -To make an "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive. +Sử dụng vòng lặp vô hạn với `while(true)` , những vòng lặp như thế này có thể dùng chỉ thị `break` để dừng lại. -If we don't want to do anything on the current iteration and would like to forward to the next one, the `continue` directive does it. +Chỉ thị `continue` để bõ qua iteration hiện thời và tiếp tục lần lặp mới. -`Break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop. +`Break/continue` hỗ trợ label. Label là cách để `break/continue` thoát khỏi các vòng lặp chồng nhau. From ea5d97cbc698ae7a6a727c2e3ce919a361fdcefa Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 13 Oct 2017 12:07:09 +0700 Subject: [PATCH 45/78] Update article.md --- 1-js/02-first-steps/13-switch/article.md | 62 ++++++++++++------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/1-js/02-first-steps/13-switch/article.md b/1-js/02-first-steps/13-switch/article.md index 0ac71d162d..d3abe67879 100644 --- a/1-js/02-first-steps/13-switch/article.md +++ b/1-js/02-first-steps/13-switch/article.md @@ -1,16 +1,14 @@ -# The "switch" statement +# Câu lệnh "switch" -A `switch` statement can replace multiple `if` checks. - -It gives a more descriptive way to compare a value with multiple variants. +Lệnh `switch` thay thế cho việc sử dụng nhiều `else if`. [cut] -## The syntax +## Cú pháp -The `switch` has one or more `case` blocks and an optional default. +Lệnh `switch` có một hoặc nhiều khối lệnh `case` và một khối `default`. -It looks like this: +Như thế này: ```js no-beautify switch(x) { @@ -28,13 +26,13 @@ switch(x) { } ``` -- The value of `x` is checked for a strict equality to the value from the first `case` (that is, `value1`) then to the second (`value2`) and so on. -- If the equality is found, `switch` starts to execute the code starting from the corresponding `case`, until the nearest `break` (or until the end of `switch`). -- If no case is matched then the `default` code is executed (if it exists). +- Giá trị của `x` được kiểm tra có bằng (===) với giá trị trong `case` (ở đây là, `value1`) và tiếp theo (`value2`) cứ tiếp tục như thế. +- Nếu bằng, `switch` thực thi khối lệnh trong `case` đó, cho đến khi lệnh `break` được gọi (hoặc kết thúc `switch`). +- Nếu không có `case` nào thỏa mãn, `default` được thực thi (nếu nó tồn tại). -## An example +## Ví dụ -An example of `switch` (the executed code is highlighted): +Một ví dụ với `switch` : ```js run let a = 2 + 2; @@ -56,13 +54,13 @@ switch (a) { } ``` -Here the `switch` starts to compare `a` from the first `case` variant that is `3`. The match fails. +Ở đây `switch` bắt đầu so sánh `a` từ `case` đầu tiên là `3`. phép so sánh này `false`. -Then `4`. That's a match, so the execution starts from `case 4` until the nearest `break`. +Tiếp theo là `4`. đúng, nên thực thi khối lệnh trong `case 4`. -**If there is no `break` then the execution continues with the next `case` without any checks.** +**Nếu không có `break` thì sẽ thực thi code trong các `case` tiếp theo mà không cần kiểm tra.** -An example without `break`: +Ví dụ: không có `break`: ```js run let a = 2 + 2; @@ -81,7 +79,7 @@ switch (a) { } ``` -In the example above we'll see sequential execution of three `alert`s: +Trong ví dụ trên ta thấy thực hiện 3 lần lệnh `alert`: ```js alert( 'Exactly!' ); @@ -89,10 +87,10 @@ alert( 'Too big' ); alert( "I don't know such values" ); ``` -````smart header="Any expression can be a `switch/case` argument" -Both `switch` and `case` allow arbitrary expressions. +````smart header="Biểu thức có thể là tham số của `switch/case`" +Cả `switch` và `case` chấp nhận các biểu thức. -For example: +Ví dụ: ```js run let a = "1"; @@ -109,14 +107,14 @@ switch (+a) { alert("this doesn't run"); } ``` -Here `+a` gives `1`, that's compared with `b + 1` in `case`, and the corresponding code is executed. +Ở đây `+a` trả về `1`, so sánh với `b + 1` trong `case`, thấy bằng nhau nên code được thực thi. ```` -## Grouping of "case" +## Nhóm các "case" -Several variants of `case` which share the same code can be grouped. +Nhiều giá trị `case` có cùng code thực thi có thể được nhóm lại. -For example, if we want the same code to run for `case 3` and `case 5`: +Ví dụ `case 3` và `case 5` cùng thực thi một hành động: ```js run no-beautify let a = 2 + 2; @@ -139,15 +137,15 @@ switch (a) { } ``` -Now both `3` and `5` show the same message. +Case `3` và `5` cùng hiển thị lệnh alert như nhau. -The ability to "group" cases is a side-effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`. +Nhóm cases là một hiệu ứng phụ của việc làm cách nào `switch/case` hoạt động khi không có `break`. Ở đây `case 3` bắt đầu ở dòng `(*)` và chuyển qua `case 5`, bởi vì không có `break`. -## Type matters +## Vấn đề kiểu dữ liệu -Let's emphasize that the equality check is always strict. The values must be of the same type to match. +Phép so sánh là `===` (strict). Nên các giá trị phải có cùng kiểu dữ liệu. -For example, let's consider the code: +Xem xét code sau: ```js run let arg = prompt("Enter a value?") @@ -169,6 +167,6 @@ switch (arg) { } ``` -1. For `0`, `1`, the first `alert` runs. -2. For `2` the second `alert` runs. -3. But for `3`, the result of the `prompt` is a string `"3"`, which is not strictly equal `===` to the number `3`. So we've got a dead code in `case 3`! The `default` variant will execute. +1. Với `0`, `1`, lệnh `alert` đầu tiên sẽ chạy. +2. Với `2` lệnh `alert` thứ hai sẽ chạy. +3. Nhưng với `3`, kết quả trả về của `prompt` là chuỗi `"3"`, không `===` với số `3`. nên `case 3` sẽ không chạy! nên cuối cùng `default` sẽ chạy. From d841de77ebd5f8b65eb76a1fe692ab20abc7b5c3 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:21:05 +0700 Subject: [PATCH 46/78] Update article.md --- .../14-function-basics/article.md | 182 +++++++++--------- 1 file changed, 89 insertions(+), 93 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/article.md b/1-js/02-first-steps/14-function-basics/article.md index 63ae4ff0c3..a16d92b68a 100644 --- a/1-js/02-first-steps/14-function-basics/article.md +++ b/1-js/02-first-steps/14-function-basics/article.md @@ -1,20 +1,20 @@ -# Functions +# Hàm - Functions -Quite often we need to perform a similar action in many places of the script. +Chúng ta thường thực hiện nhiều hành động tương tự nhau lặp đi lặp lại trong chương trình của mình. -For example, we need to show a nice-looking message when a visitor logs in, logs out and maybe somewhere else. +Ví dụ hiển thị những câu chào khác nhau mỗi lần người dùng đăng nhập. -Functions are the main "building blocks" of the program. They allow the code to be called many times without repetition. +Hàm là những khối gạch chính xây dựng nên chương trình. Chúng thực hiện các hành động tương tự nhau mà không lặp lại. [cut] -We've already seen examples of built-in functions, like `alert(message)`, `prompt(message, default)` and `confirm(question)`. But we can create functions of our own as well. +Ở các bài học trước chúng ta đã thấy các hàm built-in (có sẵn trong trình duyệt) như `alert(message)`, `prompt(message, default)` và `confirm(question)`. Tuy nhiên chúng ta hoàn toàn có thể tạo ra các hàm của riêng mình. -## Function Declaration +## Khai báo hàm - Function Declaration -To create a function we can use a *function declaration*. +Để tạo ra hàm và sử dụng chúng, trước tiên cần *khai báo hàm*. -It looks like this: +Như thế này: ```js function showMessage() { @@ -22,13 +22,13 @@ function showMessage() { } ``` -The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* in the brackets (empty in the example above) and finally the code of the function, also named "the function body". +Từ khóa `function` đầu tiên, tiếp theo là *tên của hàm*, tiếp là các *tham số* trong cặp dấu ngoặc (hoặc không có tham số như ví dụ trên) và cuối cùng là các dòng code trong hàm, được gọi là "thân hàm". ![](function_basics.png) -Our new function can be called by its name: `showMessage()`. +Chúng ta gọi hàm lên để sử dụng bằng tên của chúng: `showMessage()`. -For instance: +Ví dụ: ```js run function showMessage() { @@ -41,17 +41,17 @@ showMessage(); */!* ``` -The call `showMessage()` executes the code of the function. Here we will see the message two times. +Gọi `showMessage()` sẽ thực thi code trong thân hàm. Ở ví dụ trên bạn sẽ thấy xuất hiện hai thông báo. -This example clearly demonstrates one of the main purposes of functions: to evade code duplication. +Như ví dụ trên, ta thấy mục đích chính của hàm là: tránh lặp đi lặp lại việc viết code. -If we ever need to change the message or the way it is shown, it's enough to modify the code in one place: the function which outputs it. +Nếu muốn thay đổi message hoặc cách mà nó hiển thị, bạn chỉ cần sửa code một lần . Phần output của hàm được gọi sau đó sẽ thay đổi theo. -## Local variables +## Biến cục bộ - Local variables -A variable declared inside a function is only visible inside that function. +Biến khai báo trong hàm chỉ được nhìn thấy trong hàm đó. -For example: +Ví dụ: ```js run function showMessage() { @@ -67,9 +67,9 @@ showMessage(); // Hello, I'm JavaScript! alert( message ); // <-- Error! The variable is local to the function ``` -## Outer variables +## Biến ngoại vi - Outer variables -A function can access an outer variable as well, for example: +Hàm có thể truy xuất đến các biến bên ngoài hàm: ```js run no-beautify let *!*userName*/!* = 'John'; @@ -82,9 +82,9 @@ function showMessage() { showMessage(); // Hello, John ``` -The function has full access to the outer variable. It can modify it as well. +Cũng có thể gán giá trị khác cho biến ngoại vi. -For instance: +Ví dụ: ```js run let *!*userName*/!* = 'John'; @@ -103,9 +103,9 @@ showMessage(); alert( userName ); // *!*Bob*/!*, the value was modified by the function ``` -The outer variable is only used if there's no local one. So an occasional modification may happen if we forget `let`. +Biến ngoại vi chỉ được truy xuất nếu không có biến cục bộ nào cùng tên. Vì vậy đừng quên `let`. -If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`. The outer one is ignored: +Nếu trong hàm có một biến cục bộ trùng tên với một biến ngoại vi bên ngoài thì chúng là hai biến khác nhau nhé. Ví dụ bên dưới với biến `userName`: ```js run let userName = 'John'; @@ -126,18 +126,18 @@ alert( userName ); // *!*John*/!*, unchanged, the function did not access the ou ``` ```smart header="Global variables" -Variables declared outside of any function, such as the outer `userName` in the code above, are called *global*. +Tất cả các biến mà không được khai báo trong bất cứ hàm nào, như biến `userName` ở ví dụ trên, được gọi là biến *global*. -Global variables are visible from any function (unless shadowed by locals). +Biến global có thể được truy xuất bởi bất cứ hàm nào (trừ khi có biến local cùng tên). -Usually, a function declares all variables specific to its task, and global variables only store project-level data, so important that it really must be seen from anywhere. Modern code has few or no globals. Most variables reside in their functions. +Bình thường, trong hàm ta khai báo các biến có liên quan đến công việc của hàm đó, và biến global chỉ liên quan đến chương trình chung, và cần được truy xuất ở bất kỳ đâu. Các chương trình hiện nay thường chỉ có một vài, hoặc không có biến global nào. Hầu hết các biến sẽ được viết lại thành local. ``` -## Parameters +## Tham số - Parameters -We can pass arbitrary data to functions using parameters (also called *function arguments*) . +Chúng ta có thể truyền bất cứ giá trị nào vào hàm thông qua tham số, và các giá trị cụ thể đó, khi được truyền vào hàm thì ta gọi là *đối số - arguments* . -In the example below, the function has two parameters: `from` and `text`. +Trong ví dụ bên dưới, chúng ta có hai tham số là: `from` và `text`. các đối số là 'Ann', 'Hello!', và "What's up?" ```js run function showMessage(*!*from, text*/!*) { // arguments: from, text @@ -150,9 +150,9 @@ showMessage('Ann', "What's up?"); // Ann: What's up? (**) */!* ``` -When the function is called in lines `(*)` and `(**)`, the given values are copied to local variables `from` and `text`. Then the function uses them. +Khi ta gọi hàm ở dòng code `(*)` và `(**)`, Giá trị của đối số sẽ được gán vào biến cục bộ `from` và `text`. Sau đó hàm sẽ sử dụng chúng. -Here's one more example: we have a variable `from` and pass it to the function. Please note: the function changes `from`, but the change is not seen outside, because a function always gets a copy of the value: +Thêm một ví dụ nữa bên dưới: chúng ta có biến global `from` và được truyền vào hàm. Chú ý rằng: hàm sẽ gán lại giá trị cho biến cục bộ `from` trong thân hàm, nhưng giá trị của biến global `from` bên ngoài vẫn sẽ không thay đổi. Bởi vì đơn giản là hai biến này khác nhau, và khi truyền biến global `from` vào hàm thì hàm sẽ chỉ copy giá trị của nó. ```js run @@ -173,19 +173,19 @@ showMessage(from, "Hello"); // *Ann*: Hello alert( from ); // Ann ``` -## Default values +## Giá trị mặc định - Default values -If a parameter is not provided, then its value becomes `undefined`. +Ví dụ hàm có 3 tham số, mà khi bạn gọi hàm bạn chỉ truyền vào 2 đối số, vậy tham số còn lại sẽ nhận giá trị `undefined`. -For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument: +Xem ví dụ bên dưới với hàm `showMessage(from, text)`, có thể gọi hàm chỉ với một tham số: ```js showMessage("Ann"); ``` -That's not an error. Such a call would output `"Ann: undefined"`. There's no `text`, so it's assumed that `text === undefined`. +Sẽ không có lỗi xảy ra, kết quả sẽ là `"Ann: undefined"`. không truyền đối số cho `text`, cho nên `text === undefined`. -If we want to use a "default" `text` in this case, then we can specify it after `=`: +Để `text` có một giá trị mặc định, khi khai báo hàm ta truyền luôn giá trị mặc định vào bởi phép gán `=`: ```js run function showMessage(from, *!*text = "no text given"*/!*) { @@ -195,9 +195,9 @@ function showMessage(from, *!*text = "no text given"*/!*) { showMessage("Ann"); // Ann: no text given ``` -Now if the `text` parameter is not passed, it will get the value `"no text given"` +OK, bây giờ nếu không truyền đối số cho `text` thì nó sẽ nhận giá trị là `"no text given"` -Here `"no text given"` is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible: +Ở đây `"no text given"` là một chuỗi đơn giản, nhưng ta có thể đặt bất cứ giá trị phức tạo nào: ```js run function showMessage(from, text = anotherFunction()) { @@ -208,9 +208,7 @@ function showMessage(from, text = anotherFunction()) { ````smart header="Default parameters old-style" -Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts. - -For instance, an explicit check for being `undefined`: +Các phiên bản JS cũ không hỗ trợ default parameters. Nên bạn có thể dùng cách khác như bên dưới. ```js function showMessage(from, text) { @@ -238,11 +236,11 @@ function showMessage(from, text) { ```` -## Returning a value +## Giá trị trả về -A function can return a value back into the calling code as the result. +Hàm sẽ trả về một giá trị nào đó. -The simplest example would be a function that sums two values: +Ví dụ với hàm cộng hai số: ```js run no-beautify function sum(a, b) { @@ -253,9 +251,9 @@ let result = sum(1, 2); alert( result ); // 3 ``` -The directive `return` can be in any place of the function. When the execution reaches it, the function stops, and the value is returned to the calling code (assigned to `result` above). +Chỉ thị `return` có thể nằm ở bất kỳ đâu trong hàm. Khi hàm gặp chỉ thị này, nó sẽ dừng thực thi, và trả về giá trị của biểu thức nằm nay sau `return`. Ở ví dụ trên là giá trị của biểu thức `a + b` -There may be many occurrences of `return` in a single function. For instance: +Có thể có nhiều `return` trong hàm: ```js run function checkAge(age) { @@ -279,9 +277,9 @@ if ( checkAge(age) ) { } ``` -It is possible to use `return` without a value. That causes the function to exit immediately. +Có thể dùng `return` một mình, không có biểu thức nào ở sau. Đó là sự ngầm định kết thúc hàm. -For example: +Ví dụ: ```js function showMovie(age) { @@ -296,10 +294,11 @@ function showMovie(age) { } ``` -In the code above, if `checkAge(age)` returns `false`, then `showMovie` won't proceed to the `alert`. +Ở ví dụ trên `checkAge(age)` trả về `false`, nên `showMovie` không thực thi lệnh `alert`. + +````smart header="Hàm mà không có, hoặc không có gì theo sau `return` sẽ trả về `undefined`" -````smart header="A function with an empty `return` or without it returns `undefined`" -If a function does not return a value, it is the same as if it returns `undefined`: +VD: ```js run function doNothing() { /* empty */ } @@ -307,7 +306,7 @@ function doNothing() { /* empty */ } alert( doNothing() === undefined ); // true ``` -An empty `return` is also the same as `return undefined`: +VD: ```js run function doNothing() { @@ -318,38 +317,38 @@ alert( doNothing() === undefined ); // true ``` ```` -````warn header="Never add a newline between `return` and the value" -For a long expression in `return`, it might be tempting to put it on a separate line, like this: +````warn header="Không xuống dòng giữa `return` và biểu thức đằng sau" +Nếu biểu thức sau `return` quá dài, Tìm cách tách ra hợp lý, chứ đừng như bên dưới: ```js return (some + long + expression + or + whatever * f(a) + f(b)) ``` -That doesn't work, because JavaScript assumes a semicolon after `return`. That'll work the same as: +Sẽ không chạy, vì JavaScript sẽ tự thêm dấu chấm phẩy sau `return`. Và code trên sẽ thành ra như bên dưới: ```js return*!*;*/!* (some + long + expression + or + whatever * f(a) + f(b)) ``` -So, it effectively becomes an empty return. We should put the value on the same line instead. + ```` -## Naming a function [#function-naming] +## Đặt tên cho hàm [#function-naming] -Functions are actions. So their name is usually a verb. It should briefly, but as accurately as possible describe what the function does. So that a person who reads the code gets the right clue. +Hàm là một hành động. Cho nên sử dụng động từ để đặt tên cho nó. Tên cần ngắn gọn, chính xác và mô tả được những gì mà hàm thực hiện. Để cho người đọc dễ hiểu, dễ nhớ và thể hiện đẳng cấp pro của LTV ( :D, sống ảo tí ). -It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes. +Đó là cách đặt tên phổ biến của các LTV trên tg hiện nay. -For instance, functions that start with `"show"` usually show something. +Ví dụ hàm bắt đầu bằng `"show"` sẽ show lên cái gì đó. -Function starting with... +Hàm bắt đầu bằng (hay còn gọi là tiền tố - prefix): - `"get…"` -- return a value, - `"calc…"` -- calculate something, - `"create…"` -- create something, - `"check…"` -- check something and return a boolean, etc. -Examples of such names: +Ví dụ: ```js no-beautify showMessage(..) // shows a message @@ -359,39 +358,38 @@ createForm(..) // creates a form (and usually returns it) checkPermission(..) // checks a permission, returns true/false ``` -With prefixes in place, a glance at a function name gives an understanding what kind of work it does and what kind of value it returns. +Với những tiền tố như trên, chỉ cần nhìn lướt qua tên hàm, đại khái bạn biết hàm đó sẽ làm gì và trả về giá trị gì. -```smart header="One function -- one action" -A function should do exactly what is suggested by its name, no more. +```smart header="MỘT hàm -- MỘT hành động" +Một hàm chỉ làm một hành động theo tên của nó, đừng ôm đồm thêm. -Two independent actions usually deserve two functions, even if they are usually called together (in that case we can make a 3rd function that calls those two). +Hai hành động khác nhau thì nên khai báo hai hàm khác nhau, cho dù hành động này có thể gọi hành động kia (trường hợp này ta khai báo hàm thứ ba để thực hiện hai hành động). -A few examples of breaking this rule: +Một vài ví dụ: - `getAge` -- would be bad if it shows an `alert` with the age (should only get). - `createForm` -- would be bad if it modifies the document, adding a form to it (should only create it and return). - `checkPermission` -- would be bad if displays the `access granted/denied` message (should only perform the check and return the result). -These examples assume common meanings of prefixes. What they mean for you is determined by you and your team. Maybe it's pretty normal for your code to behave differently. But you should have a firm understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge. +Ý nghĩa của các prefixes là rất quan trọng, các bạn nên nắm chắc nó, biết được prefixes nào được dùng và không được dùng trong trường hợp cụ thể. +Các hàm có chung prefixes thường sẽ có chung một ý nghĩa nào đó. Ví dụ `getUserName` lấy tên người dùng, thường sẽ trả về một string chính là tên người dùng. Nó chung prefix với `getUserAge` lấy tuổi, trả về number. Chúng có điểm chung là đều lấy thông tin người dùng cả. ``` -```smart header="Ultrashort function names" -Functions that are used *very often* sometimes have ultrashort names. +```smart header="Hàm có tên cực kỳ ngắn" +Hàm được sử dụng *quá thường xuyên* thường có tên cực kỳ ngắn. -For example, [jQuery](http://jquery.com) framework defines a function `$`, [LoDash](http://lodash.com/) library has it's core function named `_`. +Ví dụ, framework [jQuery](http://jquery.com) có hàm `$`, Thư viện [LoDash](http://lodash.com/) có hàm `_`. -These are exceptions. Generally functions names should be concise, but descriptive. +Đây là những ngoại lệ. Nói chung tên hàm nên ngắn gọn, nhưng mang tính mô tả. ``` ## Functions == Comments -Functions should be short and do exactly one thing. If that thing is big, maybe it's worth it to split the function into a few smaller functions. Sometimes following this rule may not be that easy, but it's definitely a good thing. +Hàm nên ngắn gọn và làm chính xác một hành động. Nhưng có đôi khi cái hành động này nó quá lớn, viết vào một hàm thì hơi khoai, bảo trì khó, mà đọc hiểu càng khó. Vậy ta nên chia nhỏ nó ra, có thể việc này không dễ dàng gì, nhưng nên làm. -A separate function is not only easier to test and debug -- its very existence is a great comment! +Ví dụ so sánh hàm `showPrimes(n)` khai báo theo hai cách bên dưới. Hàm này show ra các số nguyên tố [prime numbers](https://en.wikipedia.org/wiki/Prime_number) nhỏ hơn `n`. -For instance, compare the two functions `showPrimes(n)` below. Each one outputs [prime numbers](https://en.wikipedia.org/wiki/Prime_number) up to `n`. - -The first variant uses a label: +Cách khai báo đầu tiên: ```js function showPrimes(n) { @@ -406,7 +404,7 @@ function showPrimes(n) { } ``` -The second variant uses an additional function `isPrime(n)` to test for primality: +Cách thứ hai, sử dụng thêm một hàm `isPrime(n)` để kiểm tra một số có phải là số nguyên tố hay không trước, rồi bỏ vào hàm `showPrimes` sau: ```js function showPrimes(n) { @@ -426,13 +424,11 @@ function isPrime(n) { } ``` -The second variant is easier to understand isn't it? Instead of the code piece we see a name of the action (`isPrime`). Sometimes people refer to such code as *self-describing*. - -So, functions can be created even if we don't intend to reuse them. They structure the code and make it readable. +Rõ ràng cách thứ hai đọc vào dễ hiểu hơn đúng không? Mặc dù có thể hàm (`isPrime`) cũng sẽ chẳng được dùng lại ở đâu cả. Code có thể dài hơn nhưng đọc vào dễ hiểu, dễ test, dễ bảo trì. -## Summary +## Tóm tắt -A function declaration looks like this: +Hàm được khai báo theo cú pháp: ```js function name(parameters, delimited, by, comma) { @@ -440,18 +436,18 @@ function name(parameters, delimited, by, comma) { } ``` -- Values passed to a function as parameters are copied to its local variables. -- A function may access outer variables. But it works only from inside out. The code outside of the function doesn't see its local variables. -- A function can return a value. If it doesn't then its result is `undefined`. +- Giá trị đối số được truyền vào tham số trong hàm bằng cách copy vào biến local. +- Hàm có thể truy xuất đến biến ngoại vi. Nhưng chỉ sử dụng bên trong hàm đó. Code bên ngoài hàm không thể truy xuất đến các biến local trong hàm. +- Hàm trả về giá trị cụ thể nào đó. Nếu không thì nó sẽ trả về `undefined`. -To make the code clean and easy to understand, it's recommended to use mainly local variables and parameters in the function, not outer variables. +Trong hàm nên chỉ sử dụng biến local, không nên sử dụng biến ngoại vi. -It is always easier to understand a function which gets parameters, works with them and returns a result than a function which gets no parameters, but modifies outer variables as a side-effect. +Chú ý đừng quên từ khóa khai báo biến trong hàm, chứ không là nó tạo/edit biến global. -Function naming: +Đặt tên cho hàm: -- A name should clearly describe what the function does. When we see a function call in the code, a good name instantly gives us an understanding what it does and returns. -- A function is an action, so function names are usually verbal. -- There exist many well-known function prefixes like `create…`, `show…`, `get…`, `check…` and so on. Use them to hint what a function does. +- Nên ngắn gọn, chính xác và có tính mô tả. +- Hàm là một hành động, cho nên dùng động từ để đặt tên. +- Sử dụng prefixes như `create…`, `show…`, `get…`, `check…`. và `.......` theo phong cách chung của tg. -Functions are the main building blocks of scripts. Now we've covered the basics, so we actually can start creating and using them. But that's only the beginning of the path. We are going to return to them many times, going more deeply into their advanced features. +Hàm là một bài học rất quan trọng. Bài này chỉ cơ bản thôi, nhưng bạn cần nắm chắc, chúng ta sẽ đi sâu hơn trong các bài sau. From 09ea026235880ca0f6a8b165610709aebf63b595 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:24:43 +0700 Subject: [PATCH 47/78] Update task.md --- .../14-function-basics/1-if-else-required/task.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/1-if-else-required/task.md b/1-js/02-first-steps/14-function-basics/1-if-else-required/task.md index 743ba78a9f..e16337f0ae 100644 --- a/1-js/02-first-steps/14-function-basics/1-if-else-required/task.md +++ b/1-js/02-first-steps/14-function-basics/1-if-else-required/task.md @@ -2,11 +2,11 @@ importance: 4 --- -# Is "else" required? +# Có cần dùng "else" không? -The following function returns `true` if the parameter `age` is greater than `18`. +Hàm sẽ trả về `true` nếu `age` lớn hơn `18`. -Otherwise it asks for a confirmation and returns its result: +Ngược lại thì người dùng nên đi hỏi phụ huynh :D : ```js function checkAge(age) { @@ -21,7 +21,7 @@ function checkAge(age) { } ``` -Will the function work differently if `else` is removed? +Có khác gì không nếu bõ `else` ? ```js function checkAge(age) { @@ -35,4 +35,4 @@ function checkAge(age) { } ``` -Is there any difference in the bahavior of these two variants? +Hai hàm trên có khác gì nhau không, và tại sao? From d9b1afc4012f36f0b92adf307e3a2da7be798c02 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:26:26 +0700 Subject: [PATCH 48/78] Update solution.md --- .../14-function-basics/1-if-else-required/solution.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md b/1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md index e41c80418a..e76470f8d4 100644 --- a/1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md +++ b/1-js/02-first-steps/14-function-basics/1-if-else-required/solution.md @@ -1 +1,2 @@ -No difference. \ No newline at end of file +Chả có gì khác. +Tại sao mà không giải thích được thì bạn nên nghĩ luôn đừng đọc tài liệu này nữa nhé ! Đơn giản vì bạn chỉ cưỡi ngựa xem hoa, đọc cũng chả có ý nghĩa gì. From d91a23f477cbe70e40c04be363bf73fc60f05d6f Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:28:36 +0700 Subject: [PATCH 49/78] Update task.md --- .../2-rewrite-function-question-or/task.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md b/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md index f70ad6fa44..258a87835e 100644 --- a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md +++ b/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/task.md @@ -2,11 +2,8 @@ importance: 4 --- -# Rewrite the function using '?' or '||' +# Viết lại hàm dùng phép '?' hoặc phép '||' -The following function returns `true` if the parameter `age` is greater than `18`. - -Otherwise it asks for a confirmation and returns its result. ```js function checkAge(age) { @@ -18,9 +15,7 @@ function checkAge(age) { } ``` -Rewrite it, to perform the same, but without `if`, in a single line. - -Make two variants of `checkAge`: +Viết lại hàm `checkAge`, sử dụng: -1. Using a question mark operator `'?'` -2. Using OR `||` +1. Phép `'?'` +2. Phép OR `||` From 19efedc8e2d5beccc409eacc0e9275fd3916e920 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:32:50 +0700 Subject: [PATCH 50/78] Update solution.md --- .../2-rewrite-function-question-or/solution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md b/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md index c8ee9618fc..6d61402444 100644 --- a/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md +++ b/1-js/02-first-steps/14-function-basics/2-rewrite-function-question-or/solution.md @@ -1,4 +1,4 @@ -Using a question mark operator `'?'`: +Dùng `'?'`: ```js function checkAge(age) { @@ -6,7 +6,7 @@ function checkAge(age) { } ``` -Using OR `||` (the shortest variant): +Dùng OR `||` : ```js function checkAge(age) { @@ -14,4 +14,4 @@ function checkAge(age) { } ``` -Note that the parentheses around `age > 18` are not required here. They exist for better readabilty. +Cặp dấu ngoặc bao quanh `age > 18` có thể bõ, nhưng nên viết vào cho dễ đọc. From bf73403009180946516849c44fdfa716eeca7bb7 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:34:10 +0700 Subject: [PATCH 51/78] Update task.md --- 1-js/02-first-steps/14-function-basics/3-min/task.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/3-min/task.md b/1-js/02-first-steps/14-function-basics/3-min/task.md index 50edd0d36f..b185cd351b 100644 --- a/1-js/02-first-steps/14-function-basics/3-min/task.md +++ b/1-js/02-first-steps/14-function-basics/3-min/task.md @@ -2,11 +2,11 @@ importance: 1 --- -# Function min(a, b) +# Hàm min(a, b) -Write a function `min(a,b)` which returns the least of two numbers `a` and `b`. +Khai báo hàm `min(a,b)` trả về giá trị nhỏ nhất trong hai số `a` và `b`. -For instance: +Ví dụ: ```js min(2, 5) == 2 From 478ae34e7c96d8e194a7b4043065349a3d82f58f Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:37:33 +0700 Subject: [PATCH 52/78] Update solution.md --- 1-js/02-first-steps/14-function-basics/3-min/solution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/3-min/solution.md b/1-js/02-first-steps/14-function-basics/3-min/solution.md index 2236d9203f..6389d1235c 100644 --- a/1-js/02-first-steps/14-function-basics/3-min/solution.md +++ b/1-js/02-first-steps/14-function-basics/3-min/solution.md @@ -1,4 +1,4 @@ -A solution using `if`: +Dùng `if`: ```js function min(a, b) { @@ -10,7 +10,7 @@ function min(a, b) { } ``` -A solution with a question mark operator `'?'`: +Pro hơn thì dùng `'?'`: ```js function min(a, b) { @@ -18,4 +18,4 @@ function min(a, b) { } ``` -P.S. In the case of an equality `a == b` it does not matter what to return. \ No newline at end of file +P.S. Trường hợp `a == b` thì trả về `a` hay `b` cũng như nhau, nên chả ảnh hưởng gì. From 7a41e1131d9155a54830f5fa23f1b96f2c9b3a1c Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:40:39 +0700 Subject: [PATCH 53/78] Update task.md --- 1-js/02-first-steps/14-function-basics/4-pow/task.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/02-first-steps/14-function-basics/4-pow/task.md b/1-js/02-first-steps/14-function-basics/4-pow/task.md index e4f885a5cc..65666a0cd9 100644 --- a/1-js/02-first-steps/14-function-basics/4-pow/task.md +++ b/1-js/02-first-steps/14-function-basics/4-pow/task.md @@ -2,9 +2,9 @@ importance: 4 --- -# Function pow(x,n) +# Hàm pow(x,n) -Write a function `pow(x,n)` that returns `x` in power `n`. Or, in other words, multiplies `x` by itself `n` times and returns the result. +Khai báo hàm `pow(x,n)` trả về giá trị `x` mũ `n` (Hàm lũy thừa đó) ```js pow(3, 2) = 3 * 3 = 9 @@ -12,8 +12,8 @@ pow(3, 3) = 3 * 3 * 3 = 27 pow(1, 100) = 1 * 1 * ...*1 = 1 ``` -Create a web-page that prompts for `x` and `n`, and then shows the result of `pow(x,n)`. +Tạo một website, hỏi người dùng nhập vào `x` và `n`, và sau đó show ra kết quả của `pow(x,n)`. [demo] -P.S. In this task the function should support only natural values of `n`: integers up from `1`. +P.S. Để đơn giản, ta quy ước `n` là số nguyên. From 8009cc5b621f1fb43ac868343d059b189cc6063d Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 21:55:52 +0700 Subject: [PATCH 54/78] Update solution.md --- 1-js/02-first-steps/14-function-basics/4-pow/solution.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/1-js/02-first-steps/14-function-basics/4-pow/solution.md b/1-js/02-first-steps/14-function-basics/4-pow/solution.md index 79eb2b442e..0b4cf4b2ac 100644 --- a/1-js/02-first-steps/14-function-basics/4-pow/solution.md +++ b/1-js/02-first-steps/14-function-basics/4-pow/solution.md @@ -21,3 +21,10 @@ if (n <= 1) { } ``` +Nếu Pro hơn thì hàm `pow(x, n)` được viết như sau: + +```js +function pow(x, n) { + return (n == 0) ? 1 : x * pow(x, n - 1); +} +``` From fe687ec2d7e7956142b16d68e5ab1d5dd5e457da Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 24 Oct 2017 22:16:46 +0700 Subject: [PATCH 55/78] Update article.md --- 1-js/02-first-steps/15-function-expressions-arrows/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/02-first-steps/15-function-expressions-arrows/article.md b/1-js/02-first-steps/15-function-expressions-arrows/article.md index a7a840d02e..140f898159 100644 --- a/1-js/02-first-steps/15-function-expressions-arrows/article.md +++ b/1-js/02-first-steps/15-function-expressions-arrows/article.md @@ -1,4 +1,4 @@ -# Function expressions and arrows +# Function expressions và arrows function In JavaScript, a function is not a "magical language structure", but a special kind of value. From f0b0c39973a0d0bba9b4ccac9e4f15746d3e1119 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 31 Oct 2017 21:18:05 +0700 Subject: [PATCH 56/78] Update article.md --- .../15-function-expressions-arrows/article.md | 114 +++++++++--------- 1 file changed, 55 insertions(+), 59 deletions(-) diff --git a/1-js/02-first-steps/15-function-expressions-arrows/article.md b/1-js/02-first-steps/15-function-expressions-arrows/article.md index 140f898159..a5636534af 100644 --- a/1-js/02-first-steps/15-function-expressions-arrows/article.md +++ b/1-js/02-first-steps/15-function-expressions-arrows/article.md @@ -1,10 +1,8 @@ # Function expressions và arrows function -In JavaScript, a function is not a "magical language structure", but a special kind of value. - [cut] -The syntax that we used before is called a *Function Declaration*: +Cú pháp khai báo hàm bài trước chúng ta học được gọi là *Function Declaration*: ```js function sayHi() { @@ -12,9 +10,9 @@ function sayHi() { } ``` -There is another syntax for creating a function that is called a *Function Expression*. +Có một cú pháp khác để tạo ra hàm, đó là *Function Expression* - biểu thức hàm. -It looks like this: +Như thế này: ```js let sayHi = function() { @@ -22,12 +20,12 @@ let sayHi = function() { }; ``` -Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the function is defined, it's just a value stored in the variable `sayHi`. +Ở trên, hàm được tạo ra và gán cho biến, giống như phép gán với các giá trị khác. Không có vấn đề gì với hàm được định nghĩa, nó là một giá trị được lưu trữ trong biến `sayHi`. -The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`". +Nghĩa là: "Tạo ra một hàm và gán nó vào một biến có tên là `sayHi`". -We can even print out that value using `alert`: +Thậm chí có thể in ra code của hàm `alert`: ```js run function sayHi() { @@ -39,15 +37,15 @@ alert( sayHi ); // shows the function code */!* ``` -Please note that the last line does not run the function, because there are no parentheses after `sayHi`. There are programming languages where any mention of a function name causes its execution, but JavaScript is not like that. +Chú ý dòng cuối cùng không thực thi hàm, bởi vì không có cặp ngoặc sau `sayHi`. Có nhiều ngôn ngữ lập trình khi gọi tên hàm thì sẽ thực thi hàm luôn, nhưng JavaScript thì không như thế. -In JavaScript, a function is a value, so we can deal with it as a value. The code above shows its string representation, which is the source code. +Trong JavaScript, hàm là một giá trị, có thể sử dụng như các giá trị khác. Ví dụ bên trên show ra một chuỗi, cũng chính là code của hàm. -It is a special value of course, in the sense that we can call it like `sayHi()`. +Đó là một giá trị đặc biệt, về mặt ý nghĩa ta có thể gọi hàm `sayHi()`. -But it's still a value. So we can work with it like with other kinds of values. +Nhưng nó vẫn là một giá trị. Nên ta có thể dùng như kiểu các giá trị khác. -We can copy a function to another variable: +Ta có thể copy hàm cho biến khác: ```js run no-beautify function sayHi() { // (1) create @@ -62,11 +60,11 @@ sayHi(); // Hello // this still works too (why wouldn't it) Here's what happens above in detail: -1. The Function Declaration `(1)` creates the function and puts it into the variable named `sayHi`. -2. Line `(2)` copies it into the variable `func`. +1. Function Declaration `(1)` tạo ra hàm và gán vào biến `sayHi`. +2. Dòng `(2)` copy giá trị của `sayhi` vào biến `func`. - Please note again: there are no parentheses after `sayHi`. If there were, then `func = sayHi()` would write *the result of the call* `sayHi()` into `func`, not *the function* `sayHi` itself. -3. Now the function can be called as both `sayHi()` and `func()`. + Chú ý một lần nữa: Không có cặp dấu ngoặc tròn sau `sayHi`. Nếu có `func = sayHi()` sẽ thực hiện gán giá trị là *kết quả của một lần gọi của hàm* `sayHi()` vào biến `func`. +3. Giờ có thể gọi hàm bằng cả hai cách `sayHi()` và `func()`. Note that we could also have used a Function Expression to declare `sayHi`, in the first line: @@ -80,8 +78,8 @@ let func = sayHi; Everything would work the same. Even more obvious what's going on, right? -````smart header="Why there's a semicolon at the end?" -There might be a question, why does Function Expression have a semicolon `;` at the end, and Function Declaration does not: +````smart header="Tại sao có dấu chấm phẩy khi kết thúc Function Expression?" +Tại sao có dấu chấm phẩy `;` khi kết thúc Function Expression? còn Function Declaration thì không: ```js function sayHi() { @@ -93,27 +91,27 @@ let sayHi = function() { }*!*;*/!* ``` -The answer is simple: -- There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc. -- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the value. So the semicolon here is not related to the Function Expression itself in any way, it just terminates the statement. +Câu trả lời đơn giản là: +- Không cần thiết có dấu `;` ở cuối các khối code và các cấu trúc ngữ pháp như `if { ... }`, `for { }`, `function f { }` ... +- Một Function Expression được sử dụng trong câu lệnh: `let sayHi = ...;`, như một giá trị. Nó không phải là khối lệnh. Dấu chấm phẩy `;` được khuyên dùng khi kết thúc câu lệnh, không quan tâm nó là giá trị gì. Vì vậy, ở đây dấu chẩm phẩy không liên quan gì đến Function Expression, nó chỉ kết thúc cho một câu lệnh. ```` -## Callback functions +## Hàm Callback -Let's look at more examples of passing functions as values and using function expressions. +Sử dụng hàm như một đối số để truyền vào trong hàm khác, sử dụng function expressions. -We'll write a function `ask(question, yes, no)` with three parameters: +Chúng ta viết hàm `ask(question, yes, no)` với ba tham số: `question` -: Text of the question +: câu hỏi `yes` -: Function to run if the answer is "Yes" +: hàm sẽ thực thi nếu câu trả lời là "Yes" `no` -: Function to run if the answer is "No" +: hàm sẽ thực thi nếu câu trả lời là "No" -The function should ask the `question` and, depending on the user's answer, call `yes()` or `no()`: +Hàm sẽ hỏi một `question` và, tùy thuộc câu trả lời mà ta sẽ gọi hàm `yes()` hay `no()`: ```js run *!* @@ -135,13 +133,13 @@ function showCancel() { ask("Do you agree?", showOk, showCancel); ``` -Before we explore how we can write it in a much shorter way, let's note that in the browser (and on the server-side in some cases) such functions are quite popular. The major difference between a real-life implementation and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such a function usually draws a nice-looking question window. But that's another story. +Ở ví dụ trên ta viết gọn hàm bằng cách sử dụng function-comment đã học ở bài trước. Cách viết như vậy là rất phổ biến hiện nay. Sự khác biệt duy nhất giữa ví dụ ở trên và code trong thực tế là trong thực tế các hàm sẽ phức tạp hơn chứ không đơn giản chỉ `confirm`, `alert`, câu hỏi cũng sẽ hiển thị một cách đẹp đẽ hơn. Nhưng đó là câu chuyện khác. -**The arguments of `ask` are called *callback functions* or just *callbacks*.** +**Các tham số của hàm `ask` được gọi là *callback functions* hay đơn giản là *callbacks*.** -The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for the "yes" answer, and `showCancel` for the "no" answer. +Ý tưởng ở đây là các hàm đó sẽ được gọi sau nếu như cần thiết. Trong ví dụ trên, `showOk` là hàm callback cho câu trả lời "yes", và `showCancel` cho câu trả lời "no". -We can use Function Expressions to write the same function much shorter: +Chúng ta sử dụng Function Expressions để viết các hàm trên gọn hơn: ```js run no-beautify function ask(question, yes, no) { @@ -159,27 +157,25 @@ ask( ``` -Here, functions are declared right inside the `ask(...)` call. They have no name, and so are called *anonymous*. Such functions are not accessible outside of `ask` (because they are not assigned to variables), but that's just what we want here. - -Such code appears in our scripts very naturally, it's in the spirit of JavaScript. +Ở trên, hàm được khai báo bên trong `ask(...)` call. Chúng nó không có tên, và được gọi là *vô danh - anonymous*. Những hàm như thế này không thể sử dụng bên ngoài `ask` (vì nó không được gán cho biến nào), nhưng đó là những gì bạn muốn. +Code như trên nhìn rất tự nhiên, đó là linh hồn của JavaScript. -```smart header="A function is a value representing an \"action\"" -Regular values like strings or numbers represent the *data*. -A function can be perceived as an *action*. +```smart header="Một hàm là một giá trị đại diện cho một hành động \"action\"" +Các giá trị thông thường như chuỗi hoặc số đại diện cho *dữ liệu*. -We can pass it between variables and run when we want. +Một hàm có thể được coi là một *hành động*. ``` -## Function Expression vs Function Declaration +## Function Expression và Function Declaration -Let's formulate the key differences between Function Declarations and Expressions. +Cùng so sánh Function Declarations và Expressions. -First, the syntax: how to see what is what in the code. +Đầu tiên là cú pháp: how to see what is what in the code. -- *Function Declaration:* a function, declared as a separate statement, in the main code flow. +- *Function Declaration:* một hàm, được khai báo trong một câu lệnh, trong main code. ```js // Function Declaration @@ -187,9 +183,9 @@ First, the syntax: how to see what is what in the code. return a + b; } ``` -- *Function Expression:* a function, created inside an expression or inside another syntax construct. +- *Function Expression:* một hàm, được tạo ra trong biểu thức hoặc trong cấu trúc cú pháp khác. - Here, the function is created at the right side of the "assignment expression =": + Ở đây, hàm được tạo ra trong về phải của biểu thức của một phép gán: ```js // Function Expression let sum = function(a, b) { @@ -197,23 +193,23 @@ First, the syntax: how to see what is what in the code. }; ``` -The more subtle difference is *when* a function is created by the JavaScript engine. +Sự khác nhau tiếp theo là *khi nào* hàm sẽ được JavaScript engine tạo ra. -**A Function Expression is created when the execution reaches it and is usable from then on.** +**Một Function Expression được tạo ra khi chương trình chạy đến code này, và từ đó về sau ta có thể sử dụng được hàm.** -Once the execution flow passes to the right side of the assignment `let sum = function…` -- here we go, the function is created and can be used (assigned, called etc) from now on. +Khi chương trình chạy đến vế phải của biểu thức `let sum = function…` -- Đi thôi, hàm được tạo ra và có thể sử dụng rồi (gán, gọi ,...). -Function Declarations are different. +Function Declarations thì khác. -**A Function Declaration is usable in the whole script/code block.** +**Một Function Declaration có thể được sử dụng trong toàn bộ script/code block.** -In other words, when JavaScript *prepares* to run the script or a code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". +Nói cách khác, Khi JavaScript *chuẩn bị* chạy script hoặc một code block, đầu tiên nó sẽ tìm tất cả Function Declarations sau đó tạo ra các hàm này. -And after all of the Function Declarations are processed, the execution goes on. +Sau khi tất cả Function Declaration đã thực hiện xong, script/code block mới thực thi. -As a result, a function declared as a Function Declaration can be called earlier than it is defined. +Kết quả là hàm có thể gọi trước khi Function Declaration. -For example, this works: +Ví dụ: ```js run refresh untrusted *!* @@ -225,9 +221,9 @@ function sayHi(name) { } ``` -The Function Declaration `sayHi` is created when JavaScript is preparing to start the script and is visible everywhere in it. +Function Declaration `sayHi` được tạo ra khi JavaScript chuẩn bị chạy chương trình. -...If it was a Function Expression, then it wouldn't work: +...Nếu là một Function Expression, sẽ không chạy được: ```js run refresh untrusted *!* @@ -239,9 +235,9 @@ let sayHi = function(name) { // (*) no magic any more }; ``` -Function Expressions are created when the execution reaches them. That would happen only in the line `(*)`. Too late. +Function Expressions chỉ được tạo ra khi chương trình thực thi đến nó. -**When a Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.** +**Khi một Function Declaration nằm trong một code block, nó chỉ có thể được sử dụng bên trong block đó.** Sometimes that's handy to declare a local function only needed in that block alone. But that feature may also cause problems. From f53291e259438732aca1deb8b5930d7295ad23f1 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 12:17:59 +0700 Subject: [PATCH 57/78] Update article.md --- .../15-function-expressions-arrows/article.md | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/1-js/02-first-steps/15-function-expressions-arrows/article.md b/1-js/02-first-steps/15-function-expressions-arrows/article.md index a5636534af..8109f2abc1 100644 --- a/1-js/02-first-steps/15-function-expressions-arrows/article.md +++ b/1-js/02-first-steps/15-function-expressions-arrows/article.md @@ -66,7 +66,7 @@ Here's what happens above in detail: Chú ý một lần nữa: Không có cặp dấu ngoặc tròn sau `sayHi`. Nếu có `func = sayHi()` sẽ thực hiện gán giá trị là *kết quả của một lần gọi của hàm* `sayHi()` vào biến `func`. 3. Giờ có thể gọi hàm bằng cả hai cách `sayHi()` và `func()`. -Note that we could also have used a Function Expression to declare `sayHi`, in the first line: +Chú ý rằng chúng ta cũng đã sử dụng Function Expression để khai báo `sayHi`, ở dòng đầu tiên: ```js let sayHi = function() { ... }; @@ -75,7 +75,7 @@ let func = sayHi; // ... ``` -Everything would work the same. Even more obvious what's going on, right? +Mọi thứ đều hoạt động bình thường, thậm chí rõ ràng hơn đúng không? ````smart header="Tại sao có dấu chấm phẩy khi kết thúc Function Expression?" @@ -239,11 +239,9 @@ Function Expressions chỉ được tạo ra khi chương trình thực thi đ **Khi một Function Declaration nằm trong một code block, nó chỉ có thể được sử dụng bên trong block đó.** -Sometimes that's handy to declare a local function only needed in that block alone. But that feature may also cause problems. +Đôi khi khai báo hàm trong một block code có vẽ tiện hơn. Nhưng có thể sẽ xảy ra lỗi. -For instance, let's imagine that we need to declare a function `welcome()` depending on the `age` variable that we get in run time. And then we plan to use it some time later. - -The code below doesn't work: +Ví dụ bên dưới với hàm `welcome()` code sau sẽ lỗi: ```js run let age = prompt("What is your age?", 18); @@ -269,9 +267,9 @@ welcome(); // Error: welcome is not defined */!* ``` -That's because a Function Declaration is only visible inside the code block in which it resides. +Bởi vì Function Declaration chỉ dùng được trong code block. -Here's another example: +Một ví dụ khác: ```js run let age = 16; // take 16 as an example @@ -304,11 +302,11 @@ welcome(); // Error: welcome is not defined */!* ``` -What can we do to make `welcome` visible outside of `if`? +Chúng ta sẽ làm gì để `welcome` có thể dùng được bên ngoài `if`? -The correct approach would be to use a Function Expression and assign `welcome` to the variable that is declared outside of `if` and has the proper visibility. +Sử dụng Function Expression và gán `welcome` vào một biến được khai báo bên ngoài `if`. -Now it works as intended: +Bây giờ nó hoạt động như dự định: ```js run let age = prompt("What is your age?", 18); @@ -334,7 +332,7 @@ welcome(); // ok now */!* ``` -Or we could simplify it even further using a question mark operator `?`: +Hoặc đơn giản hơn là sử dụng phép `?`: ```js run let age = prompt("What is your age?", 18); @@ -349,27 +347,27 @@ welcome(); // ok now ``` -```smart header="When to choose Function Declaration versus Function Expression?" -As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration syntax, the one we used before. It gives more freedom in how to organize our code, because we can call such functions before they are declared. +```smart header="Khi nào dùng Function Declaration và Function Expression?" +Như một quy luật, khi cần khai báo hàm, đầu tiên ta xem xét cú pháp Function Declaration, liệu hàm có dùng trước khi khai báo hay không. Nó sẽ làm cho bạn code thoải mái hơn, không lo đến việc dùng hàm trước khi khai báo. -It's also a little bit easier to look up `function f(…) {…}` in the code than `let f = function(…) {…}`. Function Declarations are more "eye-catching". +Cũng dễ nhìn và dễ tìm hơn với `function f(…) {…}` so với `let f = function(…) {…}`. -...But if a Function Declaration does not suit us for some reason (we've seen an example above), then Function Expression should be used. +...Nhưng Function Declaration không thích hợp vì một số lý do (ta đã xem xét ở trên), Do đó nên dùng Function Expression. ``` ## Arrow functions [#arrow-functions] -There's one more very simple and concise syntax for creating functions, that's often better than Function Expressions. It's called "arrow functions", because it looks like this: +Có một cú pháp ngắn gọn hơn và tốt hơn Function Expressions để khai báo hàm . Nó được gọi là "arrow functions", Vì có dấu mũi tên như này: ```js let func = (arg1, arg2, ...argN) => expression ``` -...This creates a function `func` that has arguments `arg1..argN`, evaluates the `expression` on the right side with their use and returns its result. +...Cú pháp này tạo ra một hàm `func` với các tham số `arg1..argN`, phần `expression` bên phải chính là giá trị trả về của hàm, cũng là phần thân hàm. -In other words, it's roughly the same as: +Nói cách khác, cách khai báo ở trên tương đương với: ```js let func = function(arg1, arg2, ...argN) { @@ -377,9 +375,9 @@ let func = function(arg1, arg2, ...argN) { } ``` -...But much more concise. +...nhưng ngắn gọn hơn. -Let's see an example: +Ví dụ: ```js run let sum = (a, b) => a + b; @@ -395,7 +393,7 @@ alert( sum(1, 2) ); // 3 ``` -If we have only one argument, then parentheses can be omitted, making that even shorter: +Nếu chỉ có một tham số, thì có thể bõ luôn cặp dấu ngoặc như bên dưới cho ngắn gọn hơn: ```js run // same as From af545f1651b2a18ac0ee3c23d4df78a26545982b Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 12:57:46 +0700 Subject: [PATCH 58/78] Update article.md --- .../15-function-expressions-arrows/article.md | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/1-js/02-first-steps/15-function-expressions-arrows/article.md b/1-js/02-first-steps/15-function-expressions-arrows/article.md index 8109f2abc1..9257e7a09c 100644 --- a/1-js/02-first-steps/15-function-expressions-arrows/article.md +++ b/1-js/02-first-steps/15-function-expressions-arrows/article.md @@ -405,7 +405,7 @@ let double = n => n * 2; alert( double(3) ); // 6 ``` -If there are no arguments, parentheses should be empty (but they should be present): +Nếu không có tham số nào, vẫn phải có cặp dấu ngoặc: ```js run let sayHi = () => alert("Hello!"); @@ -413,9 +413,9 @@ let sayHi = () => alert("Hello!"); sayHi(); ``` -Arrow functions can be used in the same way as Function Expressions. +Arrow functions được dùng giống như cách dùng Function Expressions. -For instance, here's the rewritten example with `welcome()`: +Ví dụ với hàm `welcome()` ở các ví dụ trước có thể viết lại như sau: ```js run let age = prompt("What is your age?", 18); @@ -427,17 +427,15 @@ let welcome = (age < 18) ? welcome(); // ok now ``` -Arrow functions may appear unfamiliar and not very readable at first, but that quickly changes as the eyes get used to the structure. +Arrow functions có thể không thân thiện lắm khi bạn mới tiếp xúc, nhưng từ từ sẽ quen. -They are very convenient for simple one-line actions, when we're just too lazy to write many words. +Chúng rất tiện lợi với các hàm đơn giản, khi bạn lười code. ```smart header="Multiline arrow functions" -The examples above took arguments from the left of `=>` and evaluated the right-side expression with them. +Đôi khi hàm phức tạp hơn với nhiều biểu thức và câu lệnh. Nếu dùng arrow function thì cần dùng cặp ngoặc nhọn, và sử dụng `return` bên trong. -Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also possible, but we should enclose them in figure brackets. Then use a normal `return` within them. - -Like this: +ví dụ: ```js run let sum = (a, b) => { // the figure bracket opens a multiline function @@ -450,26 +448,26 @@ let sum = (a, b) => { // the figure bracket opens a multiline function alert( sum(1, 2) ); // 3 ``` -```smart header="More to come" -Here we praised arrow functions for brevity. But that's not all! Arrow functions have other interesting features. We'll return to them later in the chapter . +```smart header="Nhiều hơn nữa" +Bài này chỉ giới thiệu ngắn gọn về Arrow function, thực ra còn nhiều cách thức và ý nghĩa khi sử dụng nữa. Chúng ta sẽ tìm hiểu kỹ hơn ở bài . -For now, we can already use them for one-line actions and callbacks. +Bây giờ chúng ta sử dụng nó cho one-line actions và callbacks. ``` -## Summary +## Tóm tắt -- Functions are values. They can be assigned, copied or declared in any place of the code. -- If the function is declared as a separate statement in the main code flow, that's called a "Function Declaration". -- If the function is created as a part of an expression, it's called a "Function Expression". -- Function Declarations are processed before the code block is executed. They are visible everywhere in the block. -- Function Expressions are created when the execution flow reaches them. +- Hàm cũng là giá trị. Có thể được gán, copy và khai báo ở bất kỳ đâu. +- Nếu hàm được khai báo trong câu lệnh phân biệt ở main code, thì gọi là "Function Declaration". +- Nếu hàm được tạo ra như là một phần của biểu thức thì gọi là "Function Expression". +- Function Declarations được xử lý trước khi code đươc thực thi. Cho nên có thể dùng hàm trước hoặc sau code khai báo hàm. +- Function Expressions được tạo ra khi thực thi đến đoạn code chứa nó. -In most cases when we need to declare a function, a Function Declaration is preferable, because it is visible prior to the declaration itself. That gives us more flexibility in code organization, and is usually more readable. +Function Declaration thì dễ dùng, dễ đọc hơn, không phải lo đến chuyện trước sau. -So we should use a Function Expression only when a Function Declaration is not fit for the task. We've seen a couple of examples of that in this chapter, and will see more in the future. +Nhưng nên sử dụng Function Expression vì nó thích hợp hơn cho các nhiệm vụ cần được thực thi. -Arrow functions are handy for one-liners. They come in two flavors: +Arrow functions cho các one-line-action. Nó đơn giản, và có hai dạng như bên dưới: -1. Without figure brackets: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result. -2. With figure brackets: `(...args) => { body }` -- brackets allow us to write multiple statements inside the function, but we need an explicit `return` to return something. +1. Không có cặp ngoặc nhọn: `(...args) => expression` -- bên phải là một biểu thức: hàm sẽ đánh giá và trả về giá trị của biểu thức này. +2. Có cặp ngoặc nhọn: `(...args) => { body }` -- để dùng nhiều biểu thức, câu lệnh hơn trong thân hàm, cần khai báo rõ ràng `return`. From 4425c6122c515dae2ba10bd595a67fd9c983ac5e Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 12:58:17 +0700 Subject: [PATCH 59/78] Update task.md --- .../15-function-expressions-arrows/1-rewrite-arrow/task.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/1-js/02-first-steps/15-function-expressions-arrows/1-rewrite-arrow/task.md b/1-js/02-first-steps/15-function-expressions-arrows/1-rewrite-arrow/task.md index a888ac157b..534e0efa3e 100644 --- a/1-js/02-first-steps/15-function-expressions-arrows/1-rewrite-arrow/task.md +++ b/1-js/02-first-steps/15-function-expressions-arrows/1-rewrite-arrow/task.md @@ -1,7 +1,5 @@ -# Rewrite with arrow functions - -Replace Function Expressions with arrow functions in the code: +# Viết lại hàm sử dụng arrow functions ```js run function ask(question, yes, no) { From b193884c6806e1332065e5c890a84fbe78553a86 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 22:32:25 +0700 Subject: [PATCH 60/78] Update article.md --- .../16-javascript-specials/article.md | 170 +++++++++--------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/1-js/02-first-steps/16-javascript-specials/article.md b/1-js/02-first-steps/16-javascript-specials/article.md index 5e64592dd1..d94a4470ab 100644 --- a/1-js/02-first-steps/16-javascript-specials/article.md +++ b/1-js/02-first-steps/16-javascript-specials/article.md @@ -1,25 +1,25 @@ # JavaScript specials -This chapter briefly recaps the features of JavaScript that we've learned by now, paying special attention to subtle moments. +Bài này tóm tắt lại tất cả những gì đã học, chú trọng đến những điểm đặc biệt. [cut] -## Code structure +## Cấu trúc code -Statements are delimited with a semicolon: +Các câu lệnh được phân cách với nhau bằng dấu chấm phẩy: ```js run no-beautify alert('Hello'); alert('World'); ``` -Usually, a line-break is also treated as a delimiter, so that would also work: +Thông thường cũng có thể bõ qua dấu chấm phẩy bằng cách xuống hàng: ```js run no-beautify alert('Hello') alert('World') ``` -That's called "automatic semicolon insertion". Sometimes it doesn't work, for instance: +Đó gọi là "tự động chèn dấu chấm phẩy". Trong một số trường hợp sẽ lỗi, ví dụ: ```js run alert("There will be an error after this message") @@ -27,9 +27,9 @@ alert("There will be an error after this message") [1, 2].forEach(alert) ``` -Most codestyle guides agree that we should put a semicolon after each statement. +Hầu hết các phong cách code đều khuyên dùng dấu chấm phẩy. -Semicolons are not required after code blocks `{...}` and syntax constructs with them like loops: +Dấu chấm phẩy không dùng sau các code blocks `{...}` và cấu trúc cú pháp như vòng lặp, if...: ```js function f() { @@ -41,13 +41,13 @@ for(;;) { } ``` -...But even if we can put an "extra" semicolon somewhere, that's not an error. It will be ignored. +...Nhưng dù có thêm dấu chấm phẩy thì cũng sẽ không có lỗi gì, nó sẽ được bỏ qua. -More in: . +Tìm hiểu thêm tại: . ## Strict mode -To fully enable all features of modern JavaScript, we should start scripts with `"use strict"`. +Để hỗ trợ đầy đủ các tính năng trong phiên bản JavaScript hiện đại nhất, nên sử dụng `"use strict"` ở đầu script. ```js 'use strict'; @@ -55,67 +55,67 @@ To fully enable all features of modern JavaScript, we should start scripts with ... ``` -The directive must be at the top of a script or at the beginning of a function. +Chỉ thị này phải nằm đầu tiên của script hoặc hàm. -Without `"use strict"`, everything still works, but some features behave in the old-fashion, "compatible" way. We'd generally prefer the modern behavior. +Nếu không có `"use strict"`, code vẫn chạy, nhưng một số tính năng sẽ chạy theo cách cũ, chúng ta thì luôn muốn mọi thứ mới mẽ và cập nhật đúng không. -Some modern features of the language (like classes that we'll study in the future) enable strict mode implicitly. +Một số tính năng mới (như classes sẽ được học trong các bài sau) được bật strict mode một cách ngầm định. -More in: . +Xem thêm tại: . -## Variables +## Biến -Can be declared using: +Được khai báo bởi từ khóa: - `let` -- `const` (constant, can't be changed) -- `var` (old-style, will see later) +- `const` (hằng số, không thể thay đổi giá trị) +- `var` (theo cách cũ, sẽ học sau) -A variable name can include: -- Letters and digits, but the first character may not be a digit. -- Characters `$` and `_` are normal, on par with letters. -- Non-Latin alphabets and hieroglyphs are also allowed, but commonly not used. +Tên của biến bao gồm: +- Chữ cái và chữ số, Nhưng chữ đầu tiên không thể là số. +- Ký tự `$` và `_` . +- Các ký tự không phải Latin, nhưng ít khi được sử dụng. -Variables are dynamically typed. They can store any value: +Biến là kiểu động, nghĩa là có thể gán bất cứ giá trị gì cho nó: ```js let x = 5; x = "John"; ``` -There are 7 data types: +Có 7 kiểu dữ liệu: -- `number` for both floating-point and integer numbers, -- `string` for strings, -- `boolean` for logical values: `true/false`, -- `null` -- a type with a single value `null`, meaning "empty" or "does not exist", -- `undefined` -- a type with a single value `undefined`, meaning "not assigned", -- `object` and `symbol` -- for complex data structures and unique identifiers, we didn't learn them yet. +- `number` cho số nguyên và dấu chấm động, +- `string` cho chuỗi, +- `boolean` cho các giá trị logic: `true/false`, +- `null` -- kiểu `null`, có nghĩa là "rỗng" hoặc "không tồn tại", +- `undefined` -- kiểu `undefined`, nghĩa là "chưa được gán giá trị", +- `object` và `symbol` -- cho dữ liệu phức tạp hơn và định danh duy nhất, hiện tại ta chưa học đến. -The `typeof` operator returns the type for a value, with two exceptions: +Phép `typeof` trả về kiểu dữ liệu của giá trị, với hai ngoại lệ: ```js typeof null == "object" // error in the language typeof function(){} == "function" // functions are treated specially ``` -More in: and . +Xem thêm tại: . -## Interaction +## Tương tác -We're using a browser as a working environment, so basic UI functions will be: +Chúng ta sử dụng trình duyệt làm môi trường làm việc, và có một vài hàm UI cơ bản: [`prompt(question[, default])`](mdn:api/Window/prompt) -: Ask a `question`, and return either what the visitor entered or `null` if he pressed "cancel". +: Hỏi một `câu hỏi`, trả về những gì mà user nhập vào hoặc `null` nếu user nhấn "cancel". [`confirm(question)`](mdn:api/Window/confirm) -: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`. +: Hỏi một `câu hỏi` và user có thể chọn Ok hoặc Cancel. Trả về `true/false`. [`alert(message)`](mdn:api/Window/alert) -: Output a `message`. +: In ra một `message`. -All these functions are *modal*, they pause the code execution and prevent the visitor from interacting with the page until he answers. +Các hàm trên đều là *modal*, Nghĩa là dừng sự thực thi của chương trình cho đến khi nhận được tương tác từ user. -For instance: +Ví dụ: ```js run let userName = prompt("Your name?", "Alice"); @@ -125,58 +125,58 @@ alert( "Visitor: " + userName ); // Alice alert( "Tea wanted: " + isTeaWanted ); // true ``` -More in: . +Xem thêm: . -## Operators +## Phép toán -JavaScript supports the following operators: +JavaScript hỗ trợ các phép toán sau: -Arithmetical -: Regular: `* + - /`, also `%` for the remainder and `**` for power of a number. +Số học +: Hay dùng: `* + - /`, `%` cho phép chia dư và `**` cho phép lũy thừa. - Binary plus `+` concatenates strings. And if any of the operands is a string, the other one is converted to string too: + Phép `+` cộng hai chuỗi. và nếu có một toán hạng là string thì toán hạng còn lại cũng sẽ được convert sang string: ```js run alert( '1' + 2 ); // '12', string alert( 1 + '2' ); // '12', string ``` -Assignments -: There is a simple assignment: `a = b` and combined ones like `a *= 2`. +Phép gán +: Phép gán đơn giản: `a = b` và kết hợp `a *= 2`. -Bitwise -: Bitwise operators work with integers on bit-level: see the [docs](mdn:/JavaScript/Reference/Operators/Bitwise_Operators) when they are needed. +Phép nhị phân +: Xem thêm [docs](mdn:/JavaScript/Reference/Operators/Bitwise_Operators) nếu cần. -Ternary -: The only operator with three parameters: `cond ? resultA : result B`. If `cond` is truthy, returns `resultA`, otherwise `resultB`. +Phép toán ba ngôi +: Có duy nhất một phép toán là: `cond ? resultA : result B`. nếu `cond` là đúng thì trả về `resultA`, ngược lại trả về `resultB`. -Logical operators -: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped. +Phép Logic +: Phép toán logic AND `&&` và OR `||` trả về giá trị mà phép toán dừng lại. -Comparisons -: Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal: +Phép so sánh +: So sánh bằng `==` cho các giá trị khác kiểu, conver chúng thành số (ngoại trừ `null` và `undefined` chỉ bằng chính chúng), vì thế, các giá trị ở ví dụ dưới là bằng nhau: ```js run alert( 0 == false ); // true alert( 0 == '' ); // true ``` - Other comparisons convert to a number as well. + Các phép so sánh khác cũng convert sang kiểu số. - The strict equality operator `===` doesn't do the conversion: different types always mean different values for it, so: + Phép so sánh bằng nghiêm ngặt `===` không convert: khác kiểu thì sẽ không bằng: - Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else. + Giá trị `null` và `undefined` là đặc biệt: chúng chỉ `==` chúng và không `==` thứ gì khác. - Greater/less comparisons compare strings character-by-character, other types are converted to a number. + Phép so sánh lớn hơn, nhỏ hơn so sánh hai chuỗi theo từng ký tự , các kiểu khác thì convert sang number. -Logical operators -: There are few others, like a comma operator. +Phép logic +: Có thêm một số phép logic khác, như `?`. -More in: , , . +Xem thêm tại: , , . -## Loops +## Vòng lặp -- We covered 3 types of loops: +- Chúng ta đã học ba loại vòng lặp: ```js // 1 @@ -195,18 +195,18 @@ More in: , , . } ``` -- The variable declared in `for(let...)` loop is visible only inside the loop. But we can also omit `let` and reuse an existing variable. -- Directives `break/continue` allow to exit the whole loop/current iteration. Use labels to break nested loops. +- Biến được khai báo trong `for(let...)` chỉ được sử dụng trong vòng lặp. Nhưng chúng ta có thể bõ qua `let` để sử dụng một biến đã có sẵn. +- Chỉ thị `break/continue` để thoát hoặc tiếp tục vòng lặp. Sử dụng "label" đối với các vòng lặp lồng nhau. -Details in: . +Xem thêm tại: . -Later we'll study more types of loops to deal with objects. +Cuối cùng chúng ta sẽ học thêm nhiều kiểu vòng lặp và sử dụng với Object. -## The "switch" construct +## Cấu trúc "switch" -The "switch" construct can replace multiple `if` checks. It uses `===` for comparisons. +Cấu trúc "switch" để thay thế khi cần dùng nhiều "if". Nó sử dụng `===` để so sánh điều kiện. -For instance: +Ví dụ: ```js run let age = prompt('Your age?', 18); @@ -224,13 +224,13 @@ switch (age) { } ``` -Details in: . +Xem thêm tại: . -## Functions +## Hàm -We covered three ways to create a function in JavaScript: +Chúng ta đã học ba cách để tạo ra hàm trong JavaScript: -1. Function Declaration: the function in the main code flow +1. Function Declaration: Khai báo hàm trong main code flow ```js function sum(a, b) { @@ -240,7 +240,7 @@ We covered three ways to create a function in JavaScript: } ``` -2. Function Expression: the function in the context of an expression +2. Function Expression: Khai báo hàm trong biểu thức phép gán ```js let sum = function(a, b) { @@ -250,7 +250,7 @@ We covered three ways to create a function in JavaScript: } ``` - Function expression can have a name, like `sum = function name(a, b)`, but that `name` is only visible inside that function. + Function expression có tên, như `sum = function name(a, b)`, nhưng tên này `name` chỉ dùng được bên trong hàm. 3. Arrow functions: @@ -272,18 +272,18 @@ We covered three ways to create a function in JavaScript: ``` -- Functions may have local variables: those declared inside its body. Such variables are only visible inside the function. -- Parameters can have default values: `function sum(a = 1, b = 2) {...}`. -- Functions always return something. If there's no `return` statement, then the result is `undefined`. +- Hàm có biến cục bộ: Là các biến được khai báo bên trong thân hàm, và chỉ sử dụng được bên trong hàm đó. +- Tham số có giá trị mặc định: `function sum(a = 1, b = 2) {...}`. +- Hàm có thể trả về giá trị nào đó. Nếu không có lệnh `return` thì trả về `undefined`. | Function Declaration | Function Expression | |----------------------|---------------------| -| visible in the whole code block | created when the execution reaches it | -| - | can have a name, visible only inside the function | +| Chỉ dùng được trong code block | Được tạo ra khi JS thực thi đến code tạo ra nó | +| - | Có thể có tên, chỉ dùng được trong hàm | -More: see , . +Xem thêm , . -## More to come +## Tiếp theo -That was a brief list of JavaScript features. As of now we've studied only basics. Further in the tutorial you'll find more specials and advanced features of JavaScript. +Tóm tắt những tính năng cơ bản trong JavaScript. Tiếp theo các bài sau sẽ học các tính năng nâng cao của JavaScript. From 1ad0d8e86b5308f0eea3d2dfa2a2191fa6f7aaf7 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 22:35:15 +0700 Subject: [PATCH 61/78] Update index.md --- 1-js/03-code-quality/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/03-code-quality/index.md b/1-js/03-code-quality/index.md index 2ef64fa690..70e5ac1b85 100644 --- a/1-js/03-code-quality/index.md +++ b/1-js/03-code-quality/index.md @@ -1,3 +1,3 @@ -# Code quality +# Chất lượng code -This chapter explains coding practices that we'll use further in the development. +Chương này giải thích việc thực hành code mà chúng tôi dùng để phát triển code. From 1ab86bb9008c5ad85b74972ab533faaf2072682e Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 1 Nov 2017 23:05:04 +0700 Subject: [PATCH 62/78] Update article.md --- .../01-debugging-chrome/article.md | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/1-js/03-code-quality/01-debugging-chrome/article.md b/1-js/03-code-quality/01-debugging-chrome/article.md index 9c81d2dc79..5840943347 100644 --- a/1-js/03-code-quality/01-debugging-chrome/article.md +++ b/1-js/03-code-quality/01-debugging-chrome/article.md @@ -1,22 +1,22 @@ -# Debugging in Chrome +# Debug trên trình duyệt Chrome -Before writing more complex code, let's talk about debugging. +Trước khi viết các code phức tạp. Ta tìm hiểu về việc debug lỗi. -All modern browsers and most other environments support "debugging" -- a special UI in developer tools that makes finding and fixing errors much easier. +Các trình duyệt hiện nay đa số sẽ hỗ trợ "debugging" -- một giao diện để LTV tìm lỗi dễ dàng hơn. -We'll be using Chrome here, because it's probably the most feature-rich in this aspect. +Chúng ta sẽ sử dụng Chrome, vì hiện nay thấy nó Pro và đầy đủ nhất. [cut] -## The "sources" pane +## "sources" pane -Your Chrome version may look a little bit different, but it still should be obvious what's there. +Tùy thuộc phiên bản Chrome bạn đang dùng, có thể nhìn hơi khác tí, nhưng cơ bản thì nó cũng thế. -- Open the [example page](debugging/index.html) in Chrome. -- Turn on developer tools with `key:F12` (Mac: `key:Cmd+Opt+I`). -- Select the `sources` pane. +- Mở trang này [example page](debugging/index.html) bằng Chrome. +- Mở Developer Tool bằng phím `key:F12` (Mac: `key:Cmd+Opt+I`). +- Chọn tab `sources`. -Here's what you should see if you are doing it for the first time: +Nếu làm đúng thì bạn sẽ thấy như sau: ![](chrome-open-sources.png) @@ -28,19 +28,19 @@ Let's click it and select `index.html` and then `hello.js` in the tree view. Her Here we can see three zones: -1. **Resources zone** lists html, javascript, css and other files including images that are attached to the page. Chrome extensions may appear here too. -2. **Source zone** shows the source code. -3. **Information and control zone** is for debugging, we'll explore it soon. +1. **Resources zone** danh sách các file html, javascript, css, images liên quan đến trang đang mở. Chrome extensions có thể sẽ xuất hiện ở đây luôn. +2. **Source zone** để xem source code. +3. **Information and control zone** để debugging, tìm hiểu nó sau. -Now you could click the same toggler again to hide the resources list and give the code some space. +Click vào để ẩn/hiện các cửa sổ ## Console -If we press `Esc`, then a console opens below. We can type commands there and press `key:Enter` to execute. +Nhấn `Esc`, cửa sổ console sẽ xuất hiện, viết một câu lệnh nào đó và nhấn `key:Enter` để thực thi. -After a statement is executed, its result is shown below. +Kết quả sẽ dược in ra luôn. -For example, here `1+2` results in `3`, and `hello("debugger")` returns nothing, so the result is `undefined`: +Ví dụ `1+2` cho kết quả là `3`, và `hello("debugger")` không có return, nên kết quả là `undefined`: ![](chrome-sources-console.png) From f45dbc27be8a0ddcc017711e167dda3a79051853 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 2 Nov 2017 20:41:41 +0700 Subject: [PATCH 63/78] Update article.md --- 1-js/04-object-basics/01-object/article.md | 84 +++++++++++----------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 31e164d985..6b10f7df96 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -1,19 +1,19 @@ # Objects -As we know from the chapter , there are seven language types in JavaScript. Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever). +Như đã học ở chương , Có 7 kiểu dữ liệu trong JavaScript. Trong đó có 6 loại là nguyên thủy "primitive", bởi vì giá trị của nó chỉ bao gồm một thứ (số, chuỗi hay gì đó). -In contrast, objects are used to store keyed collections of various data and more complex entities. In JavaScript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else. +Ngược lại, objects được dùng để lưu trữ các bộ dữ liệu khác nhau và phức tạp hơn. Trong JavaScript, objects hầu như có mặt tại hầu hết khía cạnh của ngôn ngữ. Cho nên ta cần học kỹ trước khi tìm hiểu JavaScript sâu hơn. [cut] -An object can be created with figure brackets `{…}` with an optional list of *properties*. A property is a "key: value" pair, where `key` is a string (also called a "property name"), and `value` can be anything. +Một object được tạo ra bằng cặp dấu ngoặc nhọn `{…}` với các *thuộc tính - properties*. Một property là một cặp "key: value" , với `key` là một string (cũng được gọi là "tên của thuộc tính - property name"), và `value` có thể là bất cứ cái gì. -We can imagine an object as a cabinet with signed files. Every piece of data is stored in it's file by the key. It's easy to find a file by it's name or add/remove a file. +Ta có thể tưởng tượng Object là một cái tủ tài liệu. Mỗi tài liệu có tên của nó (key), nội dung tài liệu là value. Sẽ dễ tìm được tài liệu nếu nó có tên. ![](object.png) -An empty object ("empty cabinet") can be created using one of two syntaxes: +Một object rỗng ("tủ này không có tài liệu nào") có thể tạo ra bằng hai cách: ```js let user = new Object(); // "object constructor" syntax @@ -22,11 +22,13 @@ let user = {}; // "object literal" syntax ![](object-user-empty.png) -Usually, the figure brackets `{...}` are used. That declaration is called an *object literal*. +Thông thường thì ta sử dụng `{...}`, cách này gọi là *object literal*. -## Literals and properties +## Literals và properties -We can immediately put some properties into `{...}` as "key: value" pairs: +Literals hiểu nôm na là *các giá trị mà thể hiện chính nó*. Search Google để tìm hiểu thêm. Mình cũng chả hiểu lắm :D + +Có thể đưa ngay các properties vào `{...}` dưới dạng cặp "key: value": ```js let user = { // an object @@ -35,20 +37,20 @@ let user = { // an object }; ``` -A property has a key (also known as "name" or "identifier") before the colon `":"` and a value to the right of it. +Một property thì có một key (cũng được gọi là "tên" hoặc "định danh") trước dấu hai chấm `":"` và sau dấu hai chấm là value. -In the `user` object, there are two properties: +trong `user` object, có hai properties: -1. The first property has the name `"name"` and the value `"John"`. -2. The second one has the name `"age"` and the value `30`. +1. Property đầu tiên có tên là `"name"` và giá trị là `"John"`. +2. Property thứ hai có tên là `"age"` và giá trị là `30`. -The resulting `user` object can be imagined as a cabinet with two signed files labeled "name" and "age". +Tưởng tượng `user` object là một cái tủ tài liệu và có hai tài liệu được đánh nhãn là "name" và "age". ![user object](object-user.png) -We can add, remove and read files from it any time. +Chúng ta có thể thêm, lấy ra, đọc tài liệu bất cứ khi nào. -Property values are accessible using the dot notation: +Truy xuất giá trị của property bằng cách dùng dấu chấm: ```js // get fields of the object: @@ -56,7 +58,7 @@ alert( user.name ); // John alert( user.age ); // 30 ``` -The value can be of any type. Let's add a boolean one: +Giá trị có thể là bất kỳ kiểu dữ liệu nào: ```js user.isAdmin = true; @@ -64,7 +66,7 @@ user.isAdmin = true; ![user object 2](object-user-isadmin.png) -To remove a property, we can use `delete` operator: +Xóa property sử dụng `delete`: ```js delete user.age; @@ -72,7 +74,7 @@ delete user.age; ![user object 3](object-user-delete.png) -We can also use multiword property names, but then they must be quoted: +Key có thể là nhiều từ, nhưng cần có cặp dấu nháy đơn hoặc kép: ```js let user = { @@ -86,28 +88,28 @@ let user = { ````smart header="Trailing comma" -The last property in the list may end with a comma: +Property cuối cùng nên có dấu phẩy: ```js let user = { name: "John", age: 30*!*,*/!* } ``` -That is called a "trailing" or "hanging" comma. Makes it easier to add/remove/move around properties, because all lines become alike. +Dấu phẩy này gọi là "trailing" hoặc "hanging" comma. Làm cho việc add/remove/move quanh các properties dễ dàng hơn, bởi vì tất cả các dòng là như nhau. ```` -## Square brackets +## Dấu ngoặc vuông -For multiword properties, the dot access doesn't work: +Đối với properties dài, không dùng được với dấu chấm: ```js run // this would give a syntax error user.likes birds = true ``` -That's because the dot requires the key to be a valid variable identifier. That is: no spaces and other limitations. +Bởi vì dấu chấm thì đòi hỏi key phải là một biến định danh. Đó là: không có dấu space hay các dấu không hợp lệ. -There's an alternative "square bracket notation" that works with any string: +Cách thay thế là sử dụng cặp dấu ngoặc vuông: ```js run @@ -123,9 +125,9 @@ alert(user["likes birds"]); // true delete user["likes birds"]; ``` -Now everything is fine. Please note that the string inside the brackets is properly quoted (any type of quotes will do). +Chú ý key dùng trong dấu ngoặc vuông phải đặt trong cặp dấu nháy đơn hoặc kép (Để thể hiện đó là một string). -Square brackets also provide a way to obtain the property name as the result of any expression -- as opposed to a literal string -- like from a variable as follows: +Trong cặp dấu ngoặc vuông có thể đặt một biến hay một biểu thức nào đó: ```js let key = "likes birds"; @@ -134,9 +136,9 @@ let key = "likes birds"; user[key] = true; ``` -Here, the variable `key` may be calculated at run-time or depend on the user input. And then we use it to access the property. That gives us a great deal of flexibility. The dot notation cannot be used in a similar way. +Một số trường hợp `key` phụ thuộc vào cái gì đó chưa biết. Ví dụ nhập vào từ người dùng, nếu truy xuất bằng dấu chấm thì không được. -For instance: +Ví dụ: ```js run let user = { @@ -153,9 +155,9 @@ alert( user[key] ); // John (if enter "name") ### Computed properties -We can use square brackets in an object literal. That's called *computed properties*. +Dùng dấu ngoặc vuông trong object literal. Đó gọi là *computed properties*. -For instance: +Ví dụ: ```js run let fruit = prompt("Which fruit to buy?", "apple"); @@ -169,11 +171,11 @@ let bag = { alert( bag.apple ); // 5 if fruit="apple" ``` -The meaning of a computed property is simple: `[fruit]` means that the property name should be taken from `fruit`. +Việc này đơn giản là: `[fruit]` nghĩa là key của property sẽ lấy từ biến `fruit`. -So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`. +Cho nên nếu nhập vào `"apple"`, `bag` sẽ thành `{apple: 5}`. -Essentially, that works the same as: +Về bản chất, nó tương đương với: ```js run let fruit = prompt("Which fruit to buy?", "apple"); let bag = {}; @@ -182,9 +184,9 @@ let bag = {}; bag[fruit] = 5; ``` -...But looks nicer. +...nhưng nhìn pro hơn. -We can use more complex expressions inside square brackets: +Có thể sử dụng biểu thức phức tạp hơn trong dấu ngoặc vuông: ```js let fruit = 'apple'; @@ -193,16 +195,14 @@ let bag = { }; ``` -Square brackets are much more powerful than the dot notation. They allow any property names and variables. But they are also more cumbersome to write. - -So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets. +Cặp dấu ngoặc vuông có vẽ mạnh mẽ hơn dùng dấu chấm. Nhưng khi code thì có vẻ cồng kềnh hơn +Vì vậy nếu property đơn giản thì dùng dấu chấm, còn phức tạp lằng nhằng thì dùng cặp ngoặc vuông. -````smart header="Reserved words are allowed as property names" -A variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc. -But for an object property, there's no such restriction. Any name is fine: +````smart header="Các từ khóa có thể dùng làm key" +Ví dụ "for", "let", "return" ... dùng đặt tên biến thì không được nhưng dùng làm key thì vẫn ok. ```js run let obj = { @@ -214,7 +214,7 @@ let obj = { alert( obj.for + obj.let + obj.return ); // 6 ``` -Basically, any name is allowed, but there's a special one: `"__proto__"` that gets special treatment for historical reasons. For instance, we can't set it to a non-object value: +Cơ bản thì key có thể đặt tên gì cũng được ngoại trừ: `"__proto__"` that gets special treatment for historical reasons. For instance, we can't set it to a non-object value: ```js run let obj = {}; From 86ccf7ff507acee057d3f3bf8eac578de6cca20c Mon Sep 17 00:00:00 2001 From: Son Tran Date: Fri, 3 Nov 2017 20:48:31 +0700 Subject: [PATCH 64/78] Update article.md --- 1-js/04-object-basics/01-object/article.md | 229 ++++++++++----------- 1 file changed, 112 insertions(+), 117 deletions(-) diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index 6b10f7df96..9c95b06d5b 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -214,7 +214,7 @@ let obj = { alert( obj.for + obj.let + obj.return ); // 6 ``` -Cơ bản thì key có thể đặt tên gì cũng được ngoại trừ: `"__proto__"` that gets special treatment for historical reasons. For instance, we can't set it to a non-object value: +Cơ bản thì key có thể đặt tên gì cũng được ngoại trừ: `"__proto__"` Nó là tổ tiên của các Object, và không thể gán một giá trị non-object được: ```js run let obj = {}; @@ -222,22 +222,23 @@ obj.__proto__ = 5; alert(obj.__proto__); // [object Object], didn't work as intended ``` -As we see from the code, the assignment to a primitive `5` is ignored. +Bạn thấy gán `5` cho `__proto_` sẽ bị bõ qua. -That can become a source of bugs and even vulnerabilies if we intent to store arbitrary key-value pairs in an object, and allow a visitor to specify the keys. +Đó có thể sẽ là một bug trong code. Cho nên bạn cần chú ý. -In that case the visitor may choose "__proto__" as the key, and the assignment logic will be ruined (as shown above). +Trường hợp user nhập vào "__proto__" làm key chẳng hạn, và phép gán sẽ không có tác dụng. -There exist a way to make objects treat `__proto__` as a regular property, we'll cover it later, but first we need to know more about objects to understand it. -There's another data structure [Map](info:map-set-weakmap-weakset), that we'll learn in the chapter , which supports arbitrary keys. Also +Có cách để sử dụng `__proto__` như một property bình thường, chúng ta sẽ học sau, trước mắt cứ biết vậy đã. + +Có một cấu trúc dữ liệu khác [Map](info:map-set-weakmap-weakset), sẽ được học trong bài , nó hỗ trợ các key tùy ý. ```` -## Property value shorthand +## Property viết tắt -In real code we often use existing variables as values for property names. +Trong code thực tế, ta hay sử dụng các biến có sẵn làm value, và key có cùng tên với biến luôn. -For instance: +Ví dụ: ```js run function makeUser(name, age) { @@ -252,9 +253,9 @@ let user = makeUser("John", 30); alert(user.name); // John ``` -In the example above, properties have the same names as variables. The use-case of making a property from a variable is so common, that there's a special *property value shorthand* to make it shorter. +Ở ví dụ trên, properties có tên giống với tham số. Kiểu dùng này là rất phổ biến, và ta có một cách để viết ngắn gọn hơn *property viết tắt*. -Instead of `name:name` we can just write `name`, like this: +Thay vì `name:name` ta viết `name`, như này: ```js function makeUser(name, age) { @@ -268,7 +269,7 @@ function makeUser(name, age) { } ``` -We can use both normal properties and shorthands in the same object: +Có thể dùng property viết tắt trong Object (các biến này đã tồn tại trước): ```js let user = { @@ -277,9 +278,9 @@ let user = { }; ``` -## Existence check +## Kiểm tra sự tồn tại -A notable objects feature is that it's possible to access any property. There will be no error if the property doesn't exist! Accessing a non-existing property just returns `undefined`. It provides a very common way to test whether the property exists -- to get it and compare vs undefined: +Có thể truy cập trên bất kỳ property nào, nết property không tồn tại thì sẽ trả về `undefined` chứ không bị lỗi. Vậy làm sao để kiểm tra Object có một property nào đó hay không ? ```js run let user = {}; @@ -287,14 +288,14 @@ let user = {}; alert( user.noSuchProperty === undefined ); // true means "no such property" ``` -There also exists a special operator `"in"` to check for the existence of a property. +Phép toán `"in"` dùng để kiểm tra một property có tồn tại hay không. -The syntax is: +Cú pháp: ```js "key" in object ``` -For instance: +Ví dụ: ```js run let user = { name: "John", age: 30 }; @@ -303,9 +304,9 @@ alert( "age" in user ); // true, user.age exists alert( "blabla" in user ); // false, user.blabla doesn't exist ``` -Please note that on the left side of `in` there must be a *property name*. That's usually a quoted string. +Chú ý, bên trái `in` phải là *property name*. Thường là string trong dấu nháy. -If we omit quotes, that would mean a variable containing the actual name to be tested. For instance: +Không có dấu nháy để thể hiện đó là string thì có nghĩa đó là biến, ví dụ: ```js run let user = { age: 30 }; @@ -314,10 +315,10 @@ let key = "age"; alert( *!*key*/!* in user ); // true, takes the name from key and checks for such property ``` -````smart header="Using \"in\" for properties that store `undefined`" -Usually, the strict comparison `"=== undefined"` check works fine. But there's a special case when it fails, but `"in"` works correctly. +````smart header="Sử dụng \"in\" để kiểm tra các property có giá trị `undefined`" +Thông thường, phép so sánh bằng nghiêm ngặt `"=== undefined"` sẽ ok. Nhưng có nhiều trường hợp sẽ sai, dùng `"in"` sẽ luôn ok. -It's when an object property exists, but stores `undefined`: +Đó là trường hợp property tồn tại, nhưng giá trị của nó là `undefined`: ```js run let obj = { @@ -330,17 +331,17 @@ alert( "test" in obj ); // true, the property does exist! ``` -In the code above, the property `obj.test` technically exists. So the `in` operator works right. +Trong ví dụ trên `obj.test` tồn tại. Nên `in` hoạt động đúng. -Situations like this happen very rarely, because `undefined` is usually not assigned. We mostly use `null` for "unknown" or "empty" values. So the `in` operator is an exotic guest in the code. +Tình huống trên hiếm khi xảy ra vì `undefined` thường hiếm khi được dùng để gán giá trị cho biến. Người ta thường sử dụng `null` cho cho các giá trị "chưa biết" hoặc "rỗng". Vì thế `in` cũng thường ít khi được dùng. ```` -## The "for..in" loop +## Vòng lặp "for..in" -To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before. +Lặp qua các keys của Object thì ta dùng: `for..in`. Nó khác với `for(;;)` đã học trước đó nhé. -The syntax: +Cú pháp: ```js for(key in object) { @@ -348,7 +349,7 @@ for(key in object) { } ``` -For instance, let's output all properties of `user`: +Ví dụ, in ra các keys, values của `user`: ```js run let user = { @@ -365,18 +366,18 @@ for(let key in user) { } ``` -Note that all "for" constructs allow us to declare the looping variable inside the loop, like `let key` here. +Chú ý, tất cả các cấu trúc "for" cho phép khai bái biến ở trong vòng lặp, ví dụ trên là `let key`. -Also, we could use another variable name here instead of `key`. For instance, `"for(let prop in obj)"` is also widely used. +Cũng có thể dùng một biến có tên bất kỳ thay vì `key`. Ví dụ, `"for(let prop in obj)"` cũng được sử dụng rộng rãi. -### Ordered like an object +### Sắp xếp Object -Are objects ordered? In other words, if we loop over an object, do we get all properties in the same order that they are added in it? Can we rely on it? +Các đối tượng có được sắp xếp hay không? Nói cách khác, khi ta loop qua một Object, thì sẽ theo thứ tự từ trên xuống dưới hay như nào ? -The short answer is: "ordered in a special fashion": integer properties are sorted, others appear in creation order. The details follow. +Câu trả lời là: "Được sắp xếp theo cách đặc biệt": property có key là số nguyên sẽ được sắp xếp và cũng nhảy lên trước. Còn lại thì theo thứ tự từ trên xuống. -As an example, let's consider an object with the phone codes: +Ví dụ Object với mã vùng điện thoại các quốc gia: ```js run let codes = { @@ -394,19 +395,17 @@ for(let code in codes) { */!* ``` -The object may be used to suggest a list of options to the user. If we're making a site mainly for German audience then we probably want `49` to be the first. +Khi chạy code ta sẽ thấy: -But if we run the code, we see a totally different picture: +- USA (1) in ra trước. +- Tiếp theo là Switzerland (41) và tiếp đến các mã vùng khác. -- USA (1) goes first -- then Switzerland (41) and so on. +Như vậy các property đã được sắp xếp, bởi vì chúng là số nguyên `1, 41, 44, 49`. -The phone codes go in the ascending sorted order, because they are integers. So we see `1, 41, 44, 49`. +````smart header="Integer properties? nó là cái gì?" +"integer property" là cái key dạng "interger" như ví dụ trên. Có thể convert sang number mà không thay đổi gì. -````smart header="Integer properties? What's that?" -The "integer property" term here means a string that can be converted to-and-from an integer without a change. - -So, "49" is an integer property name, because when it's transformed to an integer number and back, it's still the same. But "+49" and "1.2" are not: +vậy, "49" là một integer property, bởi vì nó có thể convert sang number và ngược lại. Nhưng "+49" và "1.2" thì không: ```js run // Math.trunc is a built-in function that removes the decimal part @@ -416,7 +415,7 @@ alert( String(Math.trunc(Number("1.2"))) ); // "1", not same ⇒ not integer pro ``` ```` -...On the other hand, if the keys are non-integer, then they are listed in the creation order, for instance: +...Nếu key là non-integer thì nó sẽ theo thứ tự từ trên xuống: ```js run let user = { @@ -433,9 +432,9 @@ for (let prop in user) { } ``` -So, to fix the issue with the phone codes, we can "cheat" by making the codes non-integer. Adding a plus `"+"` sign before each code is enough. +Vì vậy với ví dụ về phone codes ở trên, ta có thể "cheat" bằng cách đưa key về dạng non-integer. Thêm dấu `"+"` đằng trước là ok. -Like this: +Như này: ```js run let codes = { @@ -451,30 +450,30 @@ for(let code in codes) { } ``` -Now it works as intended. +Nó sẽ in ra theo thứ tự như mong muốn. -## Copying by reference +## Copying bằng tham chiếu (reference) -One of the fundamental differences of objects vs primitives is that they are stored and copied "by reference". +Sự khác nhau cơ bản giữa objects và primitives là nó lưu trữ và copy giá trị bằng tham chiếu (by reference). -Primitive values: strings, numbers, booleans -- are assigned/copied "as a whole value". +Kiểu dữ liệu primitive: strings, numbers, booleans -- được gán/copy "bởi giá trị của nó". -For instance: +Ví dụ: ```js let message = "Hello!"; let phrase = message; ``` -As a result we have two independent variables, each one is storing the string `"Hello!"`. +Kết quả là hai biến sẽ cùng lưu trữ giá trị `"Hello!"`. ![](variable-copy-value.png) -Objects are not like that. +Objects không giống như thế. -**A variable stores not the object itself, but it's "address in memory", in other words "a reference" to it.** +**Một biến không lưu trữ giá trị của Object, Nó là "địa chỉ trong bộ nhớ", hay nói cách khác là "một tham chiếu".** -Here's the picture for the object: +Hơi khó hiểu đúng không, xem ví dụ sẽ rõ: ```js let user = { @@ -484,13 +483,11 @@ let user = { ![](variable-contains-reference.png) -Here, the object is stored somewhere in memory. And the variable `user` has a "reference" to it. - -**When an object variable is copied -- the reference is copied, the object is not duplicated.** +Ở đây, Object được lưu ở địa chỉ nào đó trong bộ nhớ. Và biến `user` sẽ tham chiếu "reference" đến đó. -If we imagine an object as a cabinet, then a variable is a key to it. Copying a variable duplicates the key, but not the cabinet itself. +**Khi copy một Object là copy sự tham chiếu đến giá trị được lưu.** -For instance: +Ví dụ: ```js no-beautify let user = { name: "John" }; @@ -498,11 +495,11 @@ let user = { name: "John" }; let admin = user; // copy the reference ``` -Now we have two variables, each one with the reference to the same object: +Chúng ta có hai biến, và hai biến này cùng tham chiếu đến một object: ![](variable-copy-reference.png) -We can use any variable to access the cabinet and modify its contents: +Chúng ta có thể truy xuất, chỉnh sửa giá trị bởi bất cứ biến nào: ```js run let user = { name: 'John' }; @@ -516,15 +513,15 @@ admin.name = 'Pete'; // changed by the "admin" reference alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference ``` -The example above demonstrates that there is only one object. Like if we had a cabinet with two keys and used one of them (`admin`) to get into it. Then, if we later use the other key (`user`) we would see changes. +Ví dụ trên cho ta thấy rằng chỉ có một object duy nhất. -### Comparison by reference +### So sánh bởi tham chiếu -The equality `==` and strict equality `===` operators for objects work exactly the same. +Phép `==` và `===` đối với Object hoạt động tương tự. -**Two objects are equal only if they are the same object.** +**Hai object là bằng nhau nếu chúng là một.** -For instance, two variables reference the same object, they are equal: +Ví dụ hai biến cùng tham chiếu đến một object thì bằng nhau: ```js run let a = {}; @@ -534,7 +531,7 @@ alert( a == b ); // true, both variables reference the same object alert( a === b ); // true ``` -And here two independent objects are not equal, even though both are empty: +Hai Object độc lập thì không bằng nhau, cho dù chúng nhìn thì như nhau: ```js run let a = {}; @@ -543,13 +540,13 @@ let b = {}; // two independent objects alert( a == b ); // false ``` -For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to say the truth, such comparisons are necessary very rarely and usually are a result of a coding mistake. +Vì vậy so sánh hai object `obj1 > obj2` hoặc object với primitive `obj == 5`, objects sẽ được convert sang primitives. Chúng ta sẽ học về việc so sánh object ngay bây giờ, nhưng lưu ý là việc so sánh object hiếm khi dùng đến và thường sẽ dễ tạo lỗi cho code nếu không hiểu rõ. ### Const object -An object declared as `const` *can* be changed. +Một object được khai báo bởi từ khóa `const` *vẫn có thể thay đổi*. -For instance: +Ví dụ: ```js run const user = { @@ -563,9 +560,9 @@ user.age = 25; // (*) alert(user.age); // 25 ``` -It might seem that the line `(*)` would cause an error, but no, there's totally no problem. That's because `const` fixes the value of `user` itself. And here `user` stores the reference to the same object all the time. The line `(*)` goes *inside* the object, it doesn't reassign `user`. +Bạn nghĩ rằng dòng `(*)` sẽ báo lỗi? không lỗi nhé, chẳng có vấn đề gì. Bởi vì `const` set giá trị cho `user`. Và ở đây `user` lưu trữ tham chiếu đến một object. Dòng `(*)` thay đổi object, chứ không phải `user`. -The `const` would give an error if we try to set `user` to something else, for instance: +Chỉ có lỗi nếu bạn gán `user` cho một thứ khác, ví dụ: ```js run const user = { @@ -580,19 +577,19 @@ user = { }; ``` -...But what if we want to make constant object properties? So that `user.age = 25` would give an error. That's possible too. We'll cover it in the chapter . +...Nhưng sẽ ra sao nếu dùng `const` cho object properties? và `user.age = 25` sẽ báo lỗi. Có thể được nhé, chúng ta sẽ học ở chương . -## Cloning and merging, Object.assign +## Cloning và merging, Object.assign -So, copying an object variable creates one more reference to the same object. +Copy một object chỉ là tạo ra một reference đến cùng một object. -But what if we need to duplicate an object? Create an independent copy, a clone? +Nhưng muốn copy một object ra thành một object riêng biệt thì làm sao? -That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. Actually, that's rarely needed. Copying by reference is good most of the time. +Có thể làm được nhé, nhưng hơi khó khăn, trong Javascript không có sẵn các phương thức để làm việc đó. Mà thật sự thì cũng ít khi có nhu cầu. Copy bởi reference thường dùng nhiều hơn trong đa số trường hợp. -But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. +Nhưng nếu thật sự cần làm, thì ta loop qua object và copy từng key, value là được. -Like this: +Ví dụ: ```js run let user = { @@ -615,18 +612,18 @@ clone.name = "Pete"; // changed the data in it alert( user.name ); // still John in the original object ``` -Also we can use the method [Object.assign](mdn:js/Object/assign) for that. +Cũng có thể dùng [Object.assign](mdn:js/Object/assign) copy cho lẹ. -The syntax is: +Cú pháp: ```js Object.assign(dest[, src1, src2, src3...]) ``` -- Arguments `dest`, and `src1, ..., srcN` (can be as many as needed) are objects. -- It copies the properties of all objects `src1, ..., srcN` into `dest`. In other words, properties of all arguments starting from the 2nd are copied into the 1st. Then it returns `dest`. +- Tham số `dest`, và `src1, ..., srcN` là các objects. +- Nó copy tất cả property của `src1, ..., srcN` vào `dest`. và cuối cùng trả về `dest` (sau khi đã thay đổi). -For instance, we can use it to merge several objects into one: +Ví dụ merge nhiều objects vào một object: ```js let user = { name: "John" }; @@ -641,7 +638,7 @@ Object.assign(user, permissions1, permissions2); // now user = { name: "John", canView: true, canEdit: true } ``` -If the receiving object (`user`) already has the same named property, it will be overwritten: +Nếu object (`user`) có sẵn property cùng tên, nó sẽ bị ghi đè: ```js let user = { name: "John" }; @@ -652,7 +649,7 @@ Object.assign(user, { name: "Pete", isAdmin: true }); // now user = { name: "Pete", isAdmin: true } ``` -We also can use `Object.assign` to replace the loop for simple cloning: +Ta sử dụng `Object.assign` thay thế cho loop để copy một cách ngắn gọn: ```js let user = { @@ -665,11 +662,9 @@ let clone = Object.assign({}, user); */!* ``` -It copies all properties of `user` into the empty object and returns it. Actually, the same as the loop, but shorter. +Đến nay ta chỉ dùng kiểu primitive cho properties của `user` . Nếu muốn gán object cho property ta phải làm sao? -Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. What to do with them? - -Like this: +Như này: ```js run let user = { name: "John", @@ -682,9 +677,9 @@ let user = { alert( user.sizes.height ); // 182 ``` -Now it's not enough to copy `clone.sizes = user.sizes`, because the `user.sizes` is an object, it will be copied by reference. So `clone` and `user` will share the same sizes: +Bây giờ copy `clone.sizes = user.sizes` lại không đủ rồi, vì `user.sizes` là một object và nó sẽ copy kiểu reference. Vì vậy `clone` và `user` đều có chung sizes mà không phải là 2 sizes độc lập: -Like this: +Ví dụ: ```js run let user = { name: "John", @@ -703,42 +698,42 @@ user.sizes.width++; // change a property from one place alert(clone.sizes.width); // 51, see the result from the other one ``` -To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning". +Để fix, thì ta loop qua key của user và `user[key]` và nếu là object thì loop tiếp. Việc này được gọi là "deep cloning". -There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](https://w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). In order not to reinvent the wheel, we can use a working implementation of it from the JavaScript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). +Có một thuật toán để deep cloning cho nhiều trường hợp phức tạp hơn, được gọi là [Structured cloning algorithm](https://w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). Và để cho dễ dàng tiện lợi hơn, ta có thể dùng thư viện [lodash](https://lodash.com), với phương thức deep cloning có sẵn [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). -## Summary +## Tổng kết -Objects are associative arrays with several special features. +Objects là mảng kết hợp với nhiều tính năng riêng. -They store properties (key-value pairs), where: -- Property keys must be strings or symbols (usually strings). -- Values can be of any type. +Chúng gồm các properties (cặp key-value), mà: +- Property keys phải là strings hoặc symbols (thường là strings). +- Values là bất cứ giá trị nào. -To access a property, we can use: -- The dot notation: `obj.property`. -- Square brackets notation `obj["property"]`. Square brackets allow to take the key from a variable, like `obj[varWithKey]`. +Truy xuất property ta dùng: +- Dấu chấm: `obj.property`. +- Cặp ngoặc vuông `obj["property"]`. Nó cho phép lấy key từ một biến có sẵn `obj[varWithKey]`. -Additional operators: -- To delete a property: `delete obj.prop`. -- To check if a property with the given key exists: `"key" in obj`. -- To iterate over an object: `for(let key in obj)` loop. +Các phép toán: +- Xóa property: `delete obj.prop`. +- Kiểm tra tồn tại: `"key" in obj`. +- Lặp qua Object: `for(let key in obj)`. -Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object. All operations via copied references (like adding/removing properties) are performed on the same single object. +Objects được gán hay copy bởi tham chiếu. Nói cách khác một biến lưu trữ object là tham chiếu đến địa chỉ của object đó trên bộ nhớ. -To make a "real copy" (a clone) we can use `Object.assign` or [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). +Để thực sự copy (clone) một object, ta dùng `Object.assign` hoặc [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). -What we've studied in this chapter is called a "plain object", or just `Object`. +Những gì chúng ta học trong bài này là "plain object" hay nói gọi là `Object`. -There are many other kinds of objects in JavaScript: +Có nhiều loại objects khác trong JavaScript: -- `Array` to store ordered data collections, -- `Date` to store the information about the date and time, -- `Error` to store the information about an error. -- ...And so on. +- `Array` : mãng, +- `Date` để lưu trữ dữ liệu thời gian, +- `Error` lưu trữ lỗi. +- ...và nhiều nữa. -They have their special features that we'll study later. Sometimes people say something like "Array type" or "Date type", but formally they are not types of their own, but belong to a single "object" data type. And they extend it in various ways. +Chúng ta sẽ học thêm nhiều về Object. Thỉnh thoảng người ta nói "kiểu Array" hay "Kiểu Date", Nhưng chính thức thì chúng đều là Object, chẳng qua là một sự mở rộng nào đó mà thôi. -Objects in JavaScript are very powerful. Here we've just scratched the surface of the topic that is really huge. We'll be closely working with objects and learning more about them in further parts of the tutorial. +Objects trong JavaScript là rất mạnh mẽ. Bài này khá dài nhưng thật ra chỉ là chút da lông ngoài bề mặt mà thôi. Tính năng của Object còn khổng lồ lắm. Ta sẽ học từng phần, từ từ thôi, ko cần xoắn :D From a717fac39b17d86a079e12e23ee0086468b555cd Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 4 Nov 2017 14:00:48 +0700 Subject: [PATCH 65/78] Update article.md --- .../02-garbage-collection/article.md | 117 +++++++++--------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/1-js/04-object-basics/02-garbage-collection/article.md b/1-js/04-object-basics/02-garbage-collection/article.md index 6796c43e85..8741e0d443 100644 --- a/1-js/04-object-basics/02-garbage-collection/article.md +++ b/1-js/04-object-basics/02-garbage-collection/article.md @@ -1,37 +1,37 @@ # Garbage collection -Memory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions... All that takes memory. +Quản lý bộ nhớ trong JavaScript được thực hiện tự động và chúng ta sẽ không nhìn thấy. Chúng ta tạo ra primitives, objects, functions... và tất cả chúng đều sẽ chiếm giữ tài nguyên bộ nhớ. -What happens when something is not needed any more? How does the JavaScript engine discover it and clean it up? +JavaScript engine sẽ phát hiện và xóa đi những thứ không còn hữu dụng để giải phóng bộ nhớ như thế nào? [cut] -## Reachability +## Khả năng tiếp cận - reachability -The main concept of memory management in JavaScript is *reachability*. +Khái niệm chính trong JavaScript để quản lý bộ nhớ là *reachability*. -Simply put, "reachable" values are those that are accessible or usable somehow. They are guaranteed to be stored in memory. +Các giá trị có thể truy cập được là các giá trị có lưu trong bộ nhớ. Chúng được gọi là *reachable* -1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons. +1. Có một tập hợp các giá trị reachable, và không thể xóa được. - For instance: + Ví dụ: - - Local variables and parameters of the current function. - - Variables and parameters for other functions on the current chain of nested calls. - - Global variables. - - (there are some other, internal ones as well) + - Local variables và parameters của hàm đang thực thi. + - Variables và parameters của hàm khác trong nested calls. + - Biến Global. + - (Và một số thứ khác nữa) - These values are called *roots*. + Những giá trị này được gọi là giá trị gốc - *roots*. -2. Any other value is considered reachable if it's reachable from a root by a reference or by a chain of references. +2. Những thứ khác được xem là reachable nếu nó có thể truy cập được từ một hoặc một chuỗi sự tham chiếu vào roots. - For instance, if there's an object in a local variable, and that object has a property referencing another object, that object is considered reachable. And those that it references are also reachable. Detailed examples to follow. + Ví dụ, Có một object trong local variable, và object này có các property tham chiếu đến object khác, Vậy object này là reachable. Và những objects mà nó tham chiếu đến cũng là reachable. -There's a background process in the JavaScript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that have become unreachable. +Đây là một background process (chạy trong background) trong JavaScript engine, nó được gọi là [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). Nó theo dõi các đối tượng và xóa đi nếu chúng unreachable -## A simple example +## Một ví dụ đơn giản -Here's the simplest example: +Đây là một ví dụ đơn giản: ```js // user has a reference to the object @@ -42,9 +42,9 @@ let user = { ![](memory-user-john.png) -Here the arrow depicts an object reference. The global variable `"user"` references the object `{name: "John"}` (we'll call it John for brevity). The `"name"` property of John stores a primitive, so it's painted inside the object. +Ở đây mũi tên mô tả một tham chiếu đối tượng. Biến global `"user"` tham chiếu đến đổi tượng `{name: "John"}` (ta gọi đối tượng này là John cho ngắn gọn). Key `"name"` của property của John lưu trữ một giá trị primitive, vậy nó nằm trong object. -If the value of `user` is overwritten, the reference is lost: +Nếu giá trị của `user` bị ghi đè, sự tham chiếu sẽ mất đi: ```js user = null; @@ -52,11 +52,11 @@ user = null; ![](memory-user-john-lost.png) -Now John becomes unreachable. There's no way to access it, no references to it. Garbage collector will junk the data and free the memory. +Bây giờ John đã trở thành unreachable. Không có cách nào để sử dụng (gọi) nó, không có tham chiếu đến nó. Garbage collector sẽ xóa nó để giải phóng tài nguyên bộ nhớ. -## Two references +## Hai sự tham chiếu -Now let's imagine we copied the reference from `user` to `admin`: +Giờ ta copy ( bằng tham chiếu) `user` cho `admin`: ```js // user has a reference to the object @@ -71,16 +71,16 @@ let admin = user; ![](memory-user-john-admin.png) -Now if we do the same: +Nếu ta làm tương tự: ```js user = null; ``` -...Then the object is still reachable via `admin` global variable, so it's in memory. If we overwrite `admin` too, then it can be removed. +...Thì John vẫn reachable thông qua biến global `admin`, cho nên nó vẫn tồn tại trong bộ nhớ mà không bị xóa đi. Nếu ghi đè `admin`, thì John sẽ bị xóa đi. -## Interlinked objects +## Liên kết objects -Now a more complex example. The family: +Một ví dụ phức tạp hơn: ```js function marry(man, woman) { @@ -100,15 +100,15 @@ let family = marry({ }); ``` -Function `marry` "marries" two objects by giving them references to each other and returns a new object that contains them both. +Hàm `marry` có hai đối tượng tham chiếu lẫn nhau, và return một đối tượng khác chứa giá trị nằm trong hai đối tượng đó. -The resulting memory structure: +Kết quả lưu trong bộ nhớ sẽ như thế này: ![](family.png) -As of now, all objects are reachable. +Vậy, tất cả đối tượng là reachable. -Now let's remove two references: +Ta xóa đi hai tham chiếu: ```js delete family.father; @@ -117,79 +117,78 @@ delete family.mother.husband; ![](family-delete-refs.png) -It's not enough to delete only one of these two references, because all objects would still be reachable. +Nếu chỉ delete một tham chiếu, thì tất cả object vẫn reachable. -But if we delete both, then we can see that John has no incoming reference any more: +Nếu delete cả hai thì ta thấy John sẽ unreachable: ![](family-no-father.png) -Outgoing references do not matter. Only incoming ones can make an object reachable. So, John is now unreachable and will be removed from the memory with all its data that also became unaccessible. +Tham chiếu từ John ra (outgoing reference) không có ý nghĩa. Chỉ có tham chiếu vào (incoming) mới làm đối tượng reachable. Vì vậy John hiện tại sẽ unreachable và sẽ bị xóa đi. -After garbage collection: +Sau khi garbage collection: ![](family-no-father-2.png) ## Unreachable island -It is possible that the whole island of interlinked objects becomes unreachable and is removed from the memory. - -The source object is the same as above. Then: +Island dịch ra là đảo, ốc đảo. Ở đây ám chỉ một khu vực chứa các object liên kết. +Ta có thể khiến một island trở thành unreachable: ```js family = null; ``` -The in-memory picture becomes: +Trong bộ nhớ sẽ như thế này: ![](family-no-family.png) -This example demonstrates how important the concept of reachability is. +Ví dụ này chứng minh tầm quan trọng của khả năng tiếp cận như thế nào. -It's obvious that John and Ann are still linked, both have incoming references. But that's not enough. +Hiển nhiên rằng John và Ann liên kết với nhau, cả hai đều có tham chiếu incoming. Nhưng chưa đủ. -The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island becomes unreachable and will be removed. +Object `"family"` chứa cả Ann và john không liên kết đến root, không có tham chiếu incoming nào đến nó, cho nên nó unreachable và sẽ bị xóa. -## Internal algorithms +## Thuật toán trong garbage collection -The basic garbage collection algorithm is called "mark-and-sweep". +Thuật toán cơ bản trong garbage collection là đánh dấu và quét - "mark-and-sweep". -The following "garbage collection" steps are regularly performed: +"garbage collection" hoạt động theo các bước: -- The garbage collector takes roots and "marks" (remembers) them. -- Then it visits and "marks" all references from them. -- Then it visits marked objects and marks *their* references. All visited objects are remembered, so as not to visit the same object twice in the future. -- ...And so on until there are unvisited references (reachable from the roots). -- All objects except marked ones are removed. +- Đánh dấu (mark) và ghi nhớ các roots. +- Đánh dấu tất cả các references của roots +- Xem xét và đánh dấu tất cả các tham chiếu đến các objects đã được đánh dấu ở bước 2. Tất cả các object đã được đánh dấu sẽ được ghi nhớ và không xem xét lại trong tương lai. +- ...cứ tiếp tục như thế cho đến khi đánh giá tất cả object (reachable từ roots). +- Tất cả object không được đánh dấu sẽ bị xóa đi. -For instance, let our object structure look like this: +Minh họa các bước như dưới đây: ![](garbage-collection-1.png) -We can clearly see an "unreachable island" to the right side. Now let's see how "mark-and-sweep" garbage collector deals with it. +Ta thấy "unreachable island" nằm bên phải. Giờ xem "mark-and-sweep" của garbage collector xác định nó như thế nào. -The first step marks the roots: +Bước một là đánh dấu roots: ![](garbage-collection-2.png) -Then their references are marked: +Tiếp là tham chiếu của root: ![](garbage-collection-3.png) -...And their references, while possible: +...Và tham chiếu của các object vừa rồi: ![](garbage-collection-4.png) -Now the objects that could not be visited in the process are considered unreachable and will be removed: +Giờ các object không được xem xét (không được đánh dấu) là unreachable và bị xóa: ![](garbage-collection-5.png) -That's the concept of how garbage collection works. +Đó là cách garbage collection hoạt động. -JavaScript engines apply many optimizations to make it run faster and not affect the execution. +JavaScript engines có nhiều cải tiến để garbage collection hoạt động nhanh, hiệu quả mà không ảnh hưởng đến việc thực thi chương trình của bạn. -Some of the optimizations: +Những cải tiến đó là: -- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, they can be cleaned up aggressively. Those that survive for long enough, become "old" and are examined less often. +- **Generational collection** -- objects được chia làm hai loại: "mới" và "cũ". Many objects appear, do their job and die fast, they can be cleaned up aggressively. Those that survive for long enough, become "old" and are examined less often. - **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine tries to split the garbage collection into pieces. Then the pieces are executed one by one, separately. That requires some extra bookkeeping between them to track changes, but we have many tiny delays instead of a big one. - **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. From 0dc2e4aa15596561c45186efb89a202f15c06baa Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 4 Nov 2017 14:25:53 +0700 Subject: [PATCH 66/78] Update article.md --- 1-js/04-object-basics/03-symbol/article.md | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/1-js/04-object-basics/03-symbol/article.md b/1-js/04-object-basics/03-symbol/article.md index 3983ae5620..ee2204b1ce 100644 --- a/1-js/04-object-basics/03-symbol/article.md +++ b/1-js/04-object-basics/03-symbol/article.md @@ -1,33 +1,33 @@ -# Symbol type +# Kiểu Symbol -By specification, object property keys may be either of string type, or of symbol type. Not numbers, not booleans, only strings or symbols, these two types. +Object property Keys chỉ có thể là String hoặc Sybol. Không thể là numbers, booleans... -Till now we've only seen strings. Now let's see the advantages that symbols can give us. +Trước giờ chúng ta chỉ sử dụng String để làm key, giờ ta sử dụng Sybol xem như thế nào nhé. [cut] ## Symbols -"Symbol" value represents a unique identifier. +Một giá trị "Symbol" đại diện cho định danh **duy nhất**. -A value of this type can be created using `Symbol()`: +Giá trị đó được tạo ra bởi `Symbol()`: ```js // id is a new symbol let id = Symbol(); ``` -We can also give symbol a description (also called a symbol name), mostly useful for debugging purposes: +Có thể thêm description cho Sybol (được gọi là symbol name), sẽ dễ dàng cho debug code: ```js // id is a symbol with the description "id" let id = Symbol("id"); ``` -Symbols are guaranteed to be unique. Even if we create many symbols with the same description, they are different values. The description is just a label that doesn't affect anything. +Symbols được đảm bảo là duy nhất. cho dù có cùng description, chúng vẫn khác nhau. Description chỉ là cái label thôi, không có ảnh hưởng gì. -For instance, here are two symbols with the same description -- they are not equal: +Ví dụ hai Sybols có cùng description -- Chúng không bằng nhau: ```js run let id1 = Symbol("id"); @@ -38,12 +38,12 @@ alert(id1 == id2); // false */!* ``` -If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. JavaScript symbols are different. +Nếu bạn có được học về "symbols" ở các NNLT khác rồi -- đừng nhầm lẫn. Symbol trong JavaScript là khác biệt với các NNLT khác. -````warn header="Symbols don't auto-convert to a string" -Most values in JavaScript support implicit conversion to a string. For instance, we can `alert` almost any value, and it will work. Symbols are special. They don't auto-convert. +````warn header="Symbols không bị convert sang string" +Nhiều giá trị trong JavaScript hỗ trợ việc convert qua string. Ví dụ `alert` sẽ convert giá trị truyền vào sang String. Symbols là đặc biệt, nó sẽ không bị tự động convert. -For instance, this `alert` will show an error: +ví dụ: ```js run let id = Symbol("id"); @@ -52,7 +52,7 @@ alert(id); // TypeError: Cannot convert a Symbol value to a string */!* ``` -If we really want to show a symbol, we need to call `.toString()` on it, like here: +Nếu thực sự muốn in ra một Sysbol thì dùng `.toString()` : ```js run let id = Symbol("id"); *!* @@ -60,12 +60,13 @@ alert(id.toString()); // Symbol(id), now it works */!* ``` -That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not occasionally convert one into another. +Đó là sự bảo bộ từ JS để tránh sự rối rắm. Và thực tế thì cũng chẳng ai đi convert Symbol sang String làm gì. + ```` -## "Hidden" properties +## Property ẩn -Symbols allow us to create "hidden" properties of an object, that no other part of code can occasionally access or overwrite. +Symbols giúp tạo ra các property ẩn trong object, that no other part of code can occasionally access or overwrite. For instance, if we want to store an "identifier" for the object `user`, we can use a symbol as a key for it: From 29bfb823a97d4c3254e9bd7fd5e1b223a6c38864 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sat, 4 Nov 2017 23:43:11 +0700 Subject: [PATCH 67/78] Update article.md --- 1-js/04-object-basics/03-symbol/article.md | 88 ++++++++++------------ 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/1-js/04-object-basics/03-symbol/article.md b/1-js/04-object-basics/03-symbol/article.md index ee2204b1ce..7bd8dc9788 100644 --- a/1-js/04-object-basics/03-symbol/article.md +++ b/1-js/04-object-basics/03-symbol/article.md @@ -66,9 +66,9 @@ alert(id.toString()); // Symbol(id), now it works ## Property ẩn -Symbols giúp tạo ra các property ẩn trong object, that no other part of code can occasionally access or overwrite. +Symbols giúp tạo ra các property ẩn trong object, mà *thỉnh thoảng* không cho phép truy cập hay ghi đè. -For instance, if we want to store an "identifier" for the object `user`, we can use a symbol as a key for it: +Ví dụ muốn tạo ra một định danh cho `user`, sử dụng Sybol làm key: ```js run let user = { name: "John" }; @@ -78,13 +78,11 @@ user[id] = "ID Value"; alert( user[id] ); // we can access the data using the symbol as the key ``` -What's the benefit over using `Symbol("id")` over a string `"id"`? +Sử dụng `Symbol("id")` có ưu điểm gì so với dùng String `"id"`? -Let's make the example a bit deeper to see that. +Giả sử một đoạn script khác muốn dùng property "id" của `user`, for its own purposes. Nó sẽ không ý thức được là là "id" của script nào khác hay không. -Imagine that another script wants to have its own "id" property inside `user`, for its own purposes. That may be another JavaScript library, so the scripts are completely unaware of each other. - -Then that script can create its own `Symbol("id")`, like this: +Nó tạo ra một `Symbol("id")`, như này: ```js // ... @@ -93,9 +91,9 @@ let id = Symbol("id"); user[id] = "Their id value"; ``` -There will be no conflict, because symbols are always different, even if they have the same name. +Như thế sẽ không bị trùng nhau, vì Symbol luôn khác nhau, cho dù có cùng tên. -Now note that if we used a string `"id"` instead of a symbol for the same purpose, then there *would* be a conflict: +Nếu sử dụng string `"id"` thì trong trường hợp này sẽ bị trùng: ```js run let user = { name: "John" }; @@ -109,11 +107,11 @@ user.id = "Their id value" // boom! overwritten! it did not mean to harm the colleague, but did it! ``` -### Symbols in a literal +### Symbols trong một literal -If we want to use a symbol in an object literal, we need square brackets. +Nếu sử dụng Symbol trong object literal, phải dùng cặp ngoặc vuông. -Like this: +Như này: ```js let id = Symbol("id"); @@ -125,13 +123,13 @@ let user = { */!* }; ``` -That's because we need the value from the variable `id` as the key, not the string "id". +Bởi vì ta cần giá trị của biến `id` làm key, không phải string "id". -### Symbols are skipped by for..in +### Symbols bị bõ qua trong for..in -Symbolic properties do not participate in `for..in` loop. +Symbolic properties không được truy xuất bởi vòng lặp `for..in`. -For instance: +Ví dụ: ```js run let id = Symbol("id"); @@ -149,9 +147,9 @@ for (let key in user) alert(key); // name, age (no symbols) alert( "Direct: " + user[id] ); ``` -That's a part of the general "hiding" concept. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. +Đây chính là tính "ẩn" của property có key là Symbol. -In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties: +Ngược lại, [Object.assign](mdn:js/Object/assign) sẽ copy cả string và symbol properties: ```js run let id = Symbol("id"); @@ -164,12 +162,10 @@ let clone = Object.assign({}, user); alert( clone[id] ); // 123 ``` -There's no paradox here. That's by design. The idea is that when we clone an object or merge objects, we usually want *all* properties to be copied (including symbols like `id`). - -````smart header="Property keys of other types are coerced to strings" -We can only use strings or symbols as keys in objects. Other types are converted to strings. +````smart header="Property keys của các kiểu dữ liệu khác sẽ bị convert sang strings" +Ta chỉ dùng strings hoặc symbols làm key. Kiểu dữ liệu khác sẽ bị convert sang strings. -For instance, a number `0` becomes a string `"0"` when used as a property key: +Ví dụ number `0` trở thành `"0"` nếu dùng làm property key: ```js run let obj = { @@ -184,17 +180,15 @@ alert( obj[0] ); // test (same property) ## Global symbols -As we've seen, usually all symbols are different, even if they have the same names. But sometimes we want same-named symbols to be same entities. +Như chúng ta đã thấy, thông thường tất cả các symbols đều khác nhau, ngay cả khi chúng có cùng tên. Nhưng đôi khi chúng ta muốn các symbols có cùng tên là cùng một thực thể. -For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property. +Ví dụ, các phần khác nhau của ứng dụng muốn truy cập chính xác cùng một symbol `" id "`. -To achieve that, there exists a *global symbol registry*. We can create symbols in it and access them later, and it guarantees that repeated accesses by the same name return exactly the same symbol. +Để làm điều đó ta dùng `Symbol.for(key)`. -In order to create or read a symbol in the registry, use `Symbol.for(key)`. +Nó sẽ kiểm tra trong global registry, Nếu có sẵn Symbol có description là `key`, thì sẽ trả về Symbol đó, nếu không có thì tạo ra `Symbol(key)` mới và lưu vào registry. -That call checks the global registry, and if there's a symbol described as `key`, then returns it, otherwise creates a new symbol `Symbol(key)` and stores it in the registry by the given `key`. - -For instance: +Ví dụ: ```js run // read from the global registry @@ -207,19 +201,15 @@ let idAgain = Symbol.for("id"); alert( id === idAgain ); // true ``` -Symbols inside the registry are called *global symbols*. If we want an application-wide symbol, accessible everywhere in the code -- that's what they are for. - -```smart header="That sounds like Ruby" -In some programming languages, like Ruby, there's a single symbol per name. +Symbols trong registry được gọi là *global symbols*. -In JavaScript, as we can see, that's right for global symbols. ``` ### Symbol.keyFor -For global symbols, not only `Symbol.for(key)` returns a symbol by name, but there's a reverse call: `Symbol.keyFor(sym)`, that does the reverse: returns a name by a global symbol. +Đối với global symbols, `Symbol.for(key)` trả về symbol bởi tên của nó, Còn `Symbol.keyFor(sym)` thì ngược lại, nó trả về tên của global symbol. -For instance: +Ví dụ: ```js run let sym = Symbol.for("name"); @@ -230,9 +220,9 @@ alert( Symbol.keyFor(sym) ); // name alert( Symbol.keyFor(sym2) ); // id ``` -The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and return `undefined`. +`Symbol.keyFor` chỉ dùng với global symbol trong registry. Nên nó không hoạt động với non-global symbols. Nếu Symbol không phải là global, nó trả về `undefined`. -For instance: +Ví dụ: ```js run alert( Symbol.keyFor(Symbol.for("name")) ); // name, global symbol @@ -242,9 +232,9 @@ alert( Symbol.keyFor(Symbol("name2")) ); // undefined, the argument isn't a glob ## System symbols -There exist many "system" symbols that JavaScript uses internally, and we can use them to fine-tune various aspects of our objects. +Có sẵn một số "system" symbols trong JavaScript, sử dụng với hệ thống, ta có thể sử dụng nó để tinh chỉnh một số thứ. -They are listed in the specification in the [Well-known symbols](https://tc39.github.io/ecma262/#sec-well-known-symbols) table: +Tìm hiểu ở đây [Well-known symbols](https://tc39.github.io/ecma262/#sec-well-known-symbols): - `Symbol.hasInstance` - `Symbol.isConcatSpreadable` @@ -252,21 +242,21 @@ They are listed in the specification in the [Well-known symbols](https://tc39.gi - `Symbol.toPrimitive` - ...and so on. -For instance, `Symbol.toPrimitive` allows us to describe object to primitive conversion. We'll see its use very soon. +Ví dụ, `Symbol.toPrimitive` cho phép mô tả Object để convert sang primitives. Sẽ học sau. -Other symbols will also become familiar when we study the corresponding language features. +Các Symbol khác khi học đến bạn sẽ hiểu, giờ nói cũng chả hiểu gì đâu. -## Summary +## Tổng kết -`Symbol` is a primitive type for unique identifiers. +`Symbol` là một kiểu primitive sử dụng cho định danh duy nhất. -Symbols are created with `Symbol()` call with an optional description. +Symbols được tạo ra bởi `Symbol()` với một cái tên. -Symbols are always different values, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry: `Symbol.for(key)` returns (creates if needed) a global symbol with `key` as the name. Multiple calls of `Symbol.for` return exactly the same symbol. +Symbols luôn có giá trị khác nhau, cho dù có cùng tên. Nếu muốn cùng-tên-cùng-symbol thì dùng global registry: `Symbol.for(key)`. -Symbols have two main use cases: +Symbols được dùng trong hai trường hợp: -1. "Hidden" object properties. +1. Giấu đi object properties. If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be occasionally listed. Also it won't be accessed directly, because another script does not have our symbol, so it will not occasionally intervene into its actions. So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties. From 0bd12622a848b3c9705ecca77e6605f412509f6d Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sun, 5 Nov 2017 16:01:01 +0700 Subject: [PATCH 68/78] Update article.md --- .../04-object-methods/article.md | 102 +++++++++--------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/1-js/04-object-basics/04-object-methods/article.md b/1-js/04-object-basics/04-object-methods/article.md index c3a2eb62cb..ab391c7cbd 100644 --- a/1-js/04-object-basics/04-object-methods/article.md +++ b/1-js/04-object-basics/04-object-methods/article.md @@ -1,6 +1,6 @@ # Object methods, "this" -Objects are usually created to represent entities of the real world, like users, orders and so on: +Objects thường được tạo ra và đại diện cho một thực thể nào đó trong thế giới thực, như users, orders và vv...: ```js let user = { @@ -9,15 +9,15 @@ let user = { }; ``` -And, in the real world, a user can *act*: select something from the shopping cart, login, logout etc. +Trong thế giới thực, một user có thể có các hành động: chọn mặt hàng nào đó trong shopping cart, login, logout ... -Actions are represented in JavaScript by functions in properties. +Các hành động đó được đại diện bởi một hàm trong properties. Và hàm đó ta gọi là **Method** [cut] -## Method examples +## Ví dụ về methods -For the start, let's teach the `user` to say hello: +Ta tạo một hành động nói xin chào cho `user`: ```js run let user = { @@ -34,15 +34,13 @@ user.sayHi = function() { user.sayHi(); // Hello! ``` -Here we've just used a Function Expression to create the function and assign it to the property `user.sayHi` of the object. +Sử dụng Function Expression và gán cho property `user.sayHi` của user. -Then we can call it. The user can now speak! +Hàm mà là một property của object thi được gọi là *method*. -A function that is the property of an object is called its *method*. +Vậy ở đây ta có method `sayHi` của object `user`. -So, here we've got a method `sayHi` of the object `user`. - -Of course, we could use a pre-declared function as a method, like this: +Tất nhiên ta cũng có thể khai báo hàm trước rồi gán vào property sau: ```js run let user = { @@ -62,14 +60,14 @@ user.sayHi = sayHi; user.sayHi(); // Hello! ``` -```smart header="Object-oriented programming" -When we write our code using objects to represent entities, that's called an [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming), in short: "OOP". +```smart header="Lập trình hướng đối tượng" +Khi ta dùng một đối tượng để đại diện cho một thực thể thật, đó gọi là lập trình hướng đối tượng [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming), viết tắt là "OOP". -OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That's architecture, and there are great books on that topic, like "Design Patterns: Elements of Reusable Object-Oriented Software" by E.Gamma, R.Helm, R.Johnson, J.Vissides or "Object-Oriented Analysis and Design with Applications" by G.Booch, and more. We'll scratch the surface of that topic later in the chapter . +OOP là một khái niệm lớn, nó là một môn học căn bản cho các lập trình viên. Thường thi nếu học lập trình bài bản , bạn nên học qua về OOP. Nó dạy cho bạn cách đặt tên, thuộc tính, cấu trúc ....một thực thể như thế nào khi đưa vào lập trình. ``` ### Method shorthand -There exists a shorter syntax for methods in an object literal: +Tương tự như Property shorthand như đã học, có thể khai báo một method ngắn gọn như bên dưới: ```js // these objects do the same @@ -90,21 +88,21 @@ let user = { }; ``` -As demonstrated, we can omit `"function"` and just write `sayHi()`. +Ta có thể bõ qua từ khóa `"function"` chỉ viết `sayHi()`. -To tell the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases the shorter syntax is preferred. +Thực ra thì hai cách trên không hoàn toàn tương tự. Có một sự khác nhau tinh tế liên quan đến tính kế thừa của object (sẽ học sau), Nhưng hiện tại ta chưa cần quan tâm. Viết kiểu shorthand được khuyến khích sử dụng hơn nhé. -## "this" in methods +## "this" trong methods -It's common that an object method needs to access the information stored in the object to do its job. +Khi tạo ra một method, điều hay xảy ra là ta cần lấy thông tin từ một property khác trong cùng object. -For instance, the code inside `user.sayHi()` may need the name of the `user`. +Ví dụ `user.sayHi()` cần lấy tên của `user` để in ra câu chào. -**To access the object, a method can use the `this` keyword.** +**Để truy cập object, method sử dụng từ khóa `this`.** -The value of `this` is the object "before dot", the one used to call the method. +Giá trị của `this` là object "trước dấu chấm", được sử dụng để gọi method. -For instance: +Ví dụ: ```js run let user = { @@ -122,9 +120,9 @@ let user = { user.sayHi(); // John ``` -Here during the execution of `user.sayHi()`, the value of `this` will be `user`. +Khi thực thi `user.sayHi()`, Giá trị của `this` chính là `user`. -Technically, it's also possible to access the object without `this`, by referencing it via the outer variable: +Về mặt kỹ thuật ta có thể dùng chính object đó thay cho `this`: ```js let user = { @@ -140,9 +138,9 @@ let user = { }; ``` -...But such code is unreliable. If we decide to copy `user` to another variable, e.g. `admin = user` and overwrite `user` with something else, then it will access the wrong object. +...Nhưng như thế sẽ không đáng tin cậy, khi ta copy `user` cho một biến khác `admin = user` và ghi đè `user`, khi đó sẽ truy cập sai object. -That's demonstrated below: +Ví dụ: ```js run let user = { @@ -164,13 +162,13 @@ user = null; // overwrite to make things obvious admin.sayHi(); // Whoops! inside sayHi(), the old name is used! error! ``` -If we used `this.name` instead of `user.name` inside the `alert`, then the code would work. +Nếu sử dụng `this.name` thay vì `user.name` thì `alert` sẽ chạy ok. -## "this" is not bound +## "this" không bị ràng buộc -In JavaScript, "this" keyword behaves unlike most other programming languages. First, it can be used in any function. +Trong JavaScript, "this" không giống các NNLT khác. Nó có thể dùng trong bất cứ hàm nào. -There's no syntax error in the code like that: +Không có lỗi cú pháp trong code bên dưới: ```js function sayHi() { @@ -178,9 +176,9 @@ function sayHi() { } ``` -The value of `this` is evaluated during the run-time. And it can be anything. +Giá trị của `this` được đánh giá khi chạy chương trình, nó có thể là bất cứ cái gì. -For instance, the same function may have different "this" when called from different objects: +Ví dụ, cùng một hàm nhưng có thể có "this" khác nhau khi gọi hàm ở các object khác nhau: ```js run let user = { name: "John" }; @@ -204,7 +202,7 @@ admin.f(); // Admin (this == admin) admin['f'](); // Admin (dot or square brackets access the method – doesn't matter) ``` -Actually, we can call the function without an object at all: +Thực tế ta có thể gọi this mà không cần chứa trong object nào: ```js run function sayHi() { @@ -214,28 +212,26 @@ function sayHi() { sayHi(); // undefined ``` -In this case `this` is `undefined` in strict mode. If we try to access `this.name`, there will be an error. +Trường hợp trên `this` là `undefined` trong "strict mode". Nếu truy cập `this.name`, sẽ báo lỗi. -In non-strict mode (if one forgets `use strict`) the value of `this` in such case will be the *global object* (`window` in a browser, we'll get to it later). This is a historical behavior that `"use strict"` fixes. +Trong non-strict mode (Không có `use strict`) giá trị của `this` sẽ là *global object* (`window` nếu dùng trình duyệt chạy code). Đây là một hành vi mang tính lịch sử mà `"use strict"` sử dụng. -Please note that usually a call of a function that uses `this` without an object is not normal, but rather a programming mistake. If a function has `this`, then it is usually meant to be called in the context of an object. +Chú ý là dùng `this` mà không phải trong một object là không nên, đó là một sai lầm trong code. Nếu một hàm có `this`, thì nó nên được gọi trong một ngữ cảnh object. -```smart header="The consequences of unbound `this`" -If you come from another programming language, then you are probably used to the idea of a "bound `this`", where methods defined in an object always have `this` referencing that object. +```smart header="Hậu quả của việc không ràng buộc `this`" +Các NNLT khác thường sẽ ràng buộc `this`, chúng thường định nghĩa method trong object với `this`. -In JavaScript `this` is "free", its value is evaluated at call-time and does not depend on where the method was declared, but rather on what's the object "before the dot". +Trong JavaScript `this` là "free", Giá trị của `this` sẽ được đánh giá khi chạy code, nhưng việc đó sẽ đưa đến câu hỏi là giá trị đó là object nào ?? -The concept of run-time evaluated `this` has both pluses and minuses. On the one hand, a function can be reused for different objects. On the other hand, greater flexibility opens a place for mistakes. +Nó rất linh hoạt vì `this` dùng cho object nào cũng được, nhưng cũng đồng nghĩa với việc sẽ dễ xảy ra lỗi hơn. -Here our position is not to judge whether this language design decision is good or bad. We'll understand how to work with it, how to get benefits and evade problems. +Ở đây không so sánh JavaScript sử dụng `this` so với các NNLT khác là tốt hay xấu. Mà ta cần hiểu nó hoạt động như thế nào để sử dụng một cách hiệu quả ``` ## Internals: Reference Type ```warn header="In-depth language feature" -This section covers an advanced topic, to understand certain edge-cases better. - -If you want to go on faster, it can be skipped or postponed. +Phần này là phần nâng cao. Nếu bạn muốn có thể bõ qua. Vâng, tác giả bõ qua luôn, bạn nào muốn thì đọc tiếng anh nhé. Hê hê ``` An intricate method call can lose `this`, for instance: @@ -343,13 +339,13 @@ That's a special feature of arrow functions, it's useful when we actually do not ## Summary -- Functions that are stored in object properties are called "methods". -- Methods allow objects to "act" like `object.doSomething()`. -- Methods can reference the object as `this`. +- Functions được khai báo trong một property được gọi là "methods". +- Methods cho phép object có các "hành động" như `object.doSomething()`. +- Methods có thể tham chiếu đến object bằng `this`. -The value of `this` is defined at run-time. -- When a function is declared, it may use `this`, but that `this` has no value until the function is called. -- That function can be copied between objects. -- When a function is called in the "method" syntax: `object.method()`, the value of `this` during the call is `object`. +Giá trị của `this` được định nghĩa ở run-time. +- Khi khai báo một hàm có thể dùng `this`, Nhưng `this` sẽ không có giá trị cho đến khi gọi hàm. +- Hàm đó có thể được copy bởi nhiều object. +- Khi hàm được gọi trong cú pháp của "method": `object.method()`, giá trị của `this` chính là `object`. -Please note that arrow functions are special: they have no `this`. When `this` is accessed inside an arrow function, it is taken from outside. +Chú ý Arrow-function không có `this`. Khi `this` được gọi trong Arrow-function, nó sẽ là `this` của hàm chứa arrow-function đó. From a34a50832ee7d02149e9e1dd7fcace1aea099ad5 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sun, 5 Nov 2017 19:34:42 +0700 Subject: [PATCH 69/78] Update article.md --- .../05-object-toprimitive/article.md | 98 +++++++++---------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/1-js/04-object-basics/05-object-toprimitive/article.md b/1-js/04-object-basics/05-object-toprimitive/article.md index 2bb3270019..ea1f5e5aa4 100644 --- a/1-js/04-object-basics/05-object-toprimitive/article.md +++ b/1-js/04-object-basics/05-object-toprimitive/article.md @@ -1,32 +1,32 @@ # Object to primitive conversion -What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`? +Chuyện gì xảy ra khi cộng `obj1 + obj2`, trừ `obj1 - obj2` hoặc in ra bằng `alert(obj)`? -There are special methods in objects that do the conversion. +Có một số method trong object sẽ thực hiện việc convert object sang primitive. -In the chapter we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to close it. +Trong chương chúng ta đã học nguyên tắc để convert number, string, boolean. Nhưng chưa học về việc chuyển đổi Object sang primitive. [cut] -For objects, there's no to-boolean conversion, because all objects are `true` in a boolean context. So there are only string and numeric conversions. +Đối với object sẽ không chuyển đổi qua boolean, vì tất cả object đều là `true` cho nên ta chỉ xét việc convert sang string và number. -The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter ) can be subtracted, and the result of `date1 - date2` is the time difference between two dates. +Chuyển đổi sang number khi thực hiện các phép toán số học. Ví dụ, `Date` objects (Sẽ học trong chương ) có thể thực hiện phép trừ, và kết quả của `date1 - date2` là khoảng thời gian giữa 2 dates đó. -As for the string conversion -- it usually happens when we output an object like `alert(obj)` and in similar contexts. +Chuyển đổi sang string -- thường sử dụng trong một số phương thức nào đó cần string như `alert(obj)` ... ## ToPrimitive -When an object is used in the context where a primitive is required, for instance, in an `alert` or mathematical operations, it's converted to a primitive value using the `ToPrimitive` algorithm ([specification](https://tc39.github.io/ecma262/#sec-toprimitive)). +Convert object sang kiểu primitive ta sử dụng thuật toán `ToPrimitive` ([specification](https://tc39.github.io/ecma262/#sec-toprimitive)). -That algorithm allows us to customize the conversion using a special object method. +Thuật toán này cho phép ta chỉnh sửa theo mong muốn việc convert bằng method có sẵn trong object. -Depending on the context, the conversion has a so-called "hint". +Tùy thuộc vào ngữ cảnh, chuyển đổi có cái gọi là "hint". -There are three variants: +Có ba biến thể: `"string"` -: When an operation expects a string, for object-to-string conversions, like `alert`: +: khi cần một sự chuyển đổi sang string, ví dụ `alert`: ```js // output @@ -37,7 +37,7 @@ There are three variants: ``` `"number"` -: When an operation expects a number, for object-to-number conversions, like maths: +: Khi cần một number, ví dụ: ```js // explicit conversion @@ -52,9 +52,9 @@ There are three variants: ``` `"default"` -: Occurs in rare cases when the operator is "not sure" what type to expect. +: Khi một số ít toán tử chưa biết là sẽ cần chuyển đổi sang kiểu nào. - For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them), so both strings and numbers would do. Or when an object is compared using `==` with a string, number or a symbol. + Ví dụ toán tử `+` có thể dùng với string (nối chuỗi) và numbers (phép cộng số học), hoặc phép `==` với string, number hoặc symbol. ```js // binary plus @@ -64,23 +64,23 @@ There are three variants: if (user == 1) { ... }; ``` - The greater/less operator `<>` can work with both strings and numbers too. Still, it uses "number" hint, not "default". That's for historical reasons. + Toán tử lớn hơn / nhỏ hơn `<>` cũng có thể sử dụng với string hoặc number. Nhưng nó sẽ sử dụng với "number" hint, không phải "default". Bởi nguyên nhân lịch sử. - In practice, all built-in objects except for one case (`Date` object, we'll learn it later) implement `"default"` conversion the same way as `"number"`. And probably we should do the same. + Trong thực tế tất cả built-in objects ngoại trừ một trường hợp (`Date` object, sẽ học sau) nhận `"default"` conversion giống như `"number"`. Và có lẽ chúng ta nên làm như vậy. -Please note -- there are only three hints. It's that simple. There is no "boolean" hint (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions. +Chú ý: chỉ có 3 kiểu hints. không có "boolean" hint (tất objects là `true` trong boolean) hay gì khác. Và nếu ta cho `"default"` và `"number"` giống nhau, Như hầu hết các object built-ins, thì chúng ta chỉ có hai kiểu convert. -**To do the conversion, JavaScript tries to find and call three object methods:** +**Để convert, JavaScript sẽ gọi cả ba object methods:** -1. Call `obj[Symbol.toPrimitive](hint)` if the method exists, -2. Otherwise if hint is `"string"` - - try `obj.toString()` and `obj.valueOf()`, whatever exists. -3. Otherwise if hint is `"number"` or `"default"` - - try `obj.valueOf()` and `obj.toString()`, whatever exists. +1. Gọi `obj[Symbol.toPrimitive](hint)` nếu method tồn tại, +2. Nếu không thì, nếu "hint" là `"string"` + - Gọi `obj.toString()` và `obj.valueOf()`, bất cứ method nào tồn tại. +3. Nếu không thì, nếu "hint" là `"number"` hoặc `"default"` + - Gọi `obj.toString()` và `obj.valueOf()`, bất cứ method nào tồn tại. ## Symbol.toPrimitive -Let's start from the first method. There's a built-in symbol named `Symbol.toPrimitive` that should be used to name the conversion method, like this: +Phương thức đầu tiên `Symbol.toPrimitive`. Đây là một built-in có tên gọi là `Symbol.toPrimitive` cần được đặt tên cho phương thức chuyển đổi: ```js obj[Symbol.toPrimitive] = function(hint) { @@ -89,7 +89,7 @@ obj[Symbol.toPrimitive] = function(hint) { } ``` -For instance, here `user` object implements it: +Ví dụ với `user`: ```js run let user = { @@ -108,19 +108,19 @@ alert(+user); // hint: number -> 1000 alert(user + 500); // hint: default -> 1500 ``` -As we can see from the code, `user` becomes a self-descriptive string or a money amount depending on the conversion. The single method `user[Symbol.toPrimitive]` handles all conversion cases. +Như ta thấy ở trên, `user` tự định ngĩa việc convert nó. Method `user[Symbol.toPrimitive]` thực hiện việc chuyển đổi cho tất cả các trường hợp. ## toString/valueOf -Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion. +Methods `toString` và `valueOf` có từ các bản JS cũ. Chúng không phải là symbols (symbols không tồn tại trong JS cũ), chúng cũng cung cấp cách thức để thực hiện việc convert. -If there's no `Symbol.toPrimitive` then JavaScript tries to find them and try in the order: +Nếu không có `Symbol.toPrimitive` thì JavaScript sẽ sử dụng chúng: -- `toString -> valueOf` for "string" hint. -- `valueOf -> toString` otherwise. +- `toString -> valueOf` cho "string" hint. +- `valueOf -> toString` ngược lại. -For instance, here `user` does the same as above using a combination of `toString` and `valueOf`: +Ví dụ `user` thực hiện convert như đã nói bằng việc kết hợp cả `toString` và `valueOf`: ```js run let user = { @@ -144,7 +144,7 @@ alert(+user); // valueOf -> 1000 alert(user + 500); // valueOf -> 1500 ``` -Often we want a single "catch-all" place to handle all primitive conversions. In this case we can implement `toString` only, like this: +Nếu muốn convert sang primitive cho tất cả trường hợp, ta chỉ dùng `toString`, như này: ```js run let user = { @@ -159,22 +159,20 @@ alert(user); // toString -> John alert(user + 500); // toString -> John500 ``` -In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions. - +Nếu không có `Symbol.toPrimitive` và `valueOf`, thì `toString` sẽ xử lý tất cả primitive conversions. -## ToPrimitive and ToString/ToNumber -The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive. +## ToPrimitive và ToString/ToNumber -There is no control whether `toString()` returns exactly a string, or whether `Symbol.toPrimitive` method returns a number for a hint "number". +Điều quan trọng cần biết về tất cả các phương pháp chuyển đổi nguyên thủy là chúng không nhất thiết trả về nguyên thủy "gợi ý".. -**The only mandatory thing: these methods must return a primitive.** +Không có sự kiểm soát nào cho `toString()` trả về chính xác một string, hay `Symbol.toPrimitive` method trả về number khi hint == "number". -An operation that initiated the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary. +**Điều bắt buộc duy nhất: các methods đó phải trả về một primitive.** -For instance: +ví dụ: -- Mathematical operations (except binary plus) perform `ToNumber` conversion: +- Mathematical operations (ngoại trừ + ) biểu diễn `ToNumber` conversion: ```js run let obj = { @@ -186,7 +184,7 @@ For instance: alert(obj * 2); // 4, ToPrimitive gives "2", then it becomes 2 ``` -- Binary plus checks the primitive -- if it's a string, then it does concatenation, otherwise it performs `ToNumber` and works with numbers. +- Binary plus kiểm tra primitive -- nếu là string thì nối chuỗi, ngược lại biểu diễn `ToNumber` và thực hiện phép cộng numbers. String example: ```js run @@ -211,19 +209,19 @@ For instance: ``` ```smart header="Historical notes" -For historical reasons, methods `toString` or `valueOf` *should* return a primitive: if any of them returns an object, then there's no error, but that object is ignored (like if the method didn't exist). +Vì lý do lịch sử, methods `toString` hoặc `valueOf` *nên* trả về một primitive: nếu trả về một object, sẽ không có lỗi, nhưng sẽ bị bõ qua (giống như method đó không tồn tại). -In contrast, `Symbol.toPrimitive` *must* return a primitive, otherwise, there will be an error. +Tương phản, `Symbol.toPrimitive` *phải* trả về primitive, nếu không sẽ có lỗi. ``` -## Summary +## Tổng kết -The object-to-primitive conversion is called automatically by many built-in functions and operators that expect a primitive as a value. +Object-to-primitive conversion được gọi tự động, nhưng một vài bởi một số hàm built-in và toán tử cần một giá trị primitive. -There are 3 types (hints) of it: -- `"string"` (for `alert` and other string conversions) -- `"number"` (for maths) -- `"default"` (few operators) +Có 3 kiểu gợi ý (hints) cho việc convert: +- `"string"` (cho `alert` và một số string conversion khác) +- `"number"` (cho toán học) +- `"default"` (một vài toán tử) The specification describes explicitly which operator uses which hint. There are very few operators that "don't know what to expect" and use the `"default"` hint. Usually for built-in objects `"default"` hint is handled the same way as `"number"`, so in practice the last two are often merged together. From 65a4fbc87bcb0f3189b931342186c5230771c849 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Sun, 5 Nov 2017 22:20:19 +0700 Subject: [PATCH 70/78] Update article.md --- .../06-constructor-new/article.md | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/1-js/04-object-basics/06-constructor-new/article.md b/1-js/04-object-basics/06-constructor-new/article.md index 4d77d60881..1ffce3f118 100644 --- a/1-js/04-object-basics/06-constructor-new/article.md +++ b/1-js/04-object-basics/06-constructor-new/article.md @@ -1,19 +1,19 @@ -# Constructor, operator "new" +# Constructor, toán tử "new" -The regular `{...}` syntax allows to create one object. But often we need to create many similar objects, like multiple users or menu items and so on. +Cú pháp `{...}` cho phép tạo ra một object. Nhưng khi muốn tạo ra nhiều objects tương tự nhau, Ví dụ những users hay menu items ...thì ta làm thế nào? -That can be done using constructor functions and the `"new"` operator. +Chúng ta sẽ sử dụng hàm cấu trúc "Constructer function" và toán tử `"new"`. [cut] ## Constructor function -Constructor functions technically are regular functions. There are two conventions though: +Constructor functions là một hàm như bình thường. Với 2 quy ước sau: -1. They are named with capital letter first. -2. They should be executed only with `"new"` operator. +1. Tên hàm bắt đầu bằng một chữ viết hoa. +2. Chúng chỉ được thực thi với toán tử `"new"`. -For instance: +Ví dụ: ```js run function User(name) { @@ -29,13 +29,13 @@ alert(user.name); // Jack alert(user.isAdmin); // false ``` -When a function is executed as `new User(...)`, it does the following steps: +Khi hàm được thực thi bởi `new User(...)`, nó sẽ thực hiện các bước sau: -1. A new empty object is created and assigned to `this`. -2. The function body executes. Usually it modifies `this`, adds new properties to it. -3. The value of `this` is returned. +1. Tạo ra một object rỗng và gán cho `this`. +2. Thực thi các câu lệnh trong function body. Thường là chỉnh sửa `this`, add thêm các properties. +3. Trả về `this`. -In other words, `new User(...)` does something like: +Nói cách khác, `new User(...)` sẽ thực hiện như sau: ```js function User(name) { @@ -53,7 +53,7 @@ function User(name) { } ``` -So the result of `new User("Jack")` is the same object as: +Và kết quả `new User("Jack")` là một object như này: ```js let user = { @@ -62,14 +62,14 @@ let user = { }; ``` -Now if we want to create other users, we can call `new User("Ann")`, `new User("Alice")` and so on. Much shorter than using literals every time, and also easy to read. +Bây giờ nếu muốn tạo ra một user mới, ta dùng `new User("Ann")`, `new User("Alice")` .... Sẽ ngắn hơn và cũng dể đọc hơn khi dùng object literal. -That's the main purpose of constructors -- to implement reusable object creation code. +Đó là mục đích chính của constructer -- để có thể sử dụng lại việc tạo ra object. -Let's note once again -- technically, any function can be used as a constructor. That is: any function can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`. +Chú ý -- về mặt kỹ thuậ, bất kỳ một hàm nào đều có thể dùng như constructor. Đó là: bất kỳ hàm nào đều có thể dùng với `new`, Nó sẽ thực hiện theo các bước như đã nói. Viết hoa chữ cái đầu tiên của hàm là một quy ước, để cho rõ ràng rằng nó cần được dùng với `new`. ````smart header="new function() { ... }" -If we have many lines of code all about creation of a single complex object, we can wrap them in constructor function, like this: +Nếu cần tạo ra một và chỉ một object phức tạp: ```js let user = new function() { @@ -82,14 +82,14 @@ let user = new function() { }; ``` -The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse. +Constructor sẽ không thể tái sử dụng, vì nó không được lưu vào đâu hết, chỉ tạo ra và sử dụng. .Vì vậy, trick này nhằm mục đích đóng gói code mà constructer được sử dụng một lần duy nhất. ```` ## Dual-syntax constructors: new.target -Inside a function, we can check whether it was called with `new` or without it, using a special `new.target` property. +Trong hàm, ta có thể kiểm tra liệu constructer có được gọi với toán tử `new` hay không, sử dụng `new.target` property. -It is empty for regular calls and equals the function if called with `new`: +Nó là rỗng nếu gọi hàm mà không có toán tử `new`: ```js run function User() { @@ -103,7 +103,7 @@ User(); // undefined new User(); // function User { ... } ``` -That can be used to allow both `new` and regular syntax to work the same: +Có thể sử dụng `new` hoặc không với cú pháp bên dưới: ```js run function User(name) { @@ -118,20 +118,20 @@ let john = User("John"); // redirects call to new User alert(john.name); // John ``` -This approach is sometimes used in libraries to make the syntax more flexible. Probably not a good thing to use everywhere though, because omitting `new` makes it a bit less obvious what's going on. With `new` we all know that the new object is being created, that's a good thing. +Cách này thỉnh thoảng được sử dụng trong một số thu viện để làm code linh hoạt hơn. Có lẽ không hay lắm nếu sử dụng ở bất kỳ đâu, bởi vì bỏ qua `new` sẽ làm cho code không được minh bạch. Với `new` chúng ta có thể hiểu là : à, có một object mới được tạo ra. -## Return from constructors +## Return trong constructors -Usually, constructors do not have a `return` statement. Their task is to write all necessary stuff into `this`, and it automatically becomes the result. +Bình thường, constructer không có câu lệnh `return`. Vì nó tự động trả về `this` sau khi thực hiện function body rồi. -But if there is a `return` statement, then the rule is simple: +Nhưng nếu có `return` thì quy tắc sẽ như sau: -- If `return` is called with object, then it is returned instead of `this`. -- If `return` is called with a primitive, it's ignored. +- Nếu `return` một object thì ok. ko return `this` nữa. +- Nếu `return` về một primitive, thì bõ qua. -In other words, `return` with an object returns that object, in all other cases `this` is returned. +Nói cách khác, lệnh `return` về một object thì chấp nhận, nếu không thì return `this`. -For instance, here `return` overrides `this` by returning an object: +Ví dụ: ```js run function BigUser() { @@ -144,7 +144,7 @@ function BigUser() { alert( new BigUser().name ); // Godzilla, got that object ^^ ``` -And here's an example with an empty `return` (or we could place a primitive after it, doesn't matter): +Ví dụ `return` bị bõ qua: ```js run function SmallUser() { @@ -160,10 +160,10 @@ function SmallUser() { alert( new SmallUser().name ); // John ``` -Usually constructors don't have a `return` statement. Here we mention the special behavior with returning objects mainly for the sake of completeness. +Thông thường constructer không có câu lệnh `return`. Ở đây chúng tôi đề cập đến các hành vi đặc biệt mà trả về objects chủ yếu vì sự toàn vẹn của chương trình. -````smart header="Omitting parentheses" -By the way, we can omit parentheses after `new`, if it has no arguments: +````smart header="Bõ qua cặp dấu ngoặc nhọn" +Ta có thể bõ cặp ngoặc nhọn nếu không có tham số: ```js let user = new User; // <-- no parentheses @@ -171,16 +171,16 @@ let user = new User; // <-- no parentheses let user = new User(); ``` -Omitting parentheses here is not considered a "good style", but the syntax is permitted by specification. +Nhưng không nên làm như vậy vì nó sẽ khó nhìn và khó hiểu. ```` -## Methods in constructor +## Methods trong constructor -Using constructor functions to create objects gives a great deal of flexibility. The constructor function may have parameters that define how to construct the object, and what to put in it. +Sử dụng constructor functions để tạo ra các object mang lại rất nhiều tính linh hoạt. Constructor function có thể có các tham số để định nghĩa việc tổ chức một object, và chúng ta sẽ để cái gì vào đó. -Of course, we can add to `this` not only properties, but methods as well. +Tất nhiên ta có thể add không chỉ là các properties vào `this`, methods cũng có thể add vào. -For instance, `new User(name)` below creates an object with the given `name` and the method `sayHi`: +Ví dụ, `new User(name)` tạo ra một đối tượng với tham số `name` và method `sayHi`: ```js run function User(name) { @@ -205,17 +205,17 @@ john = { */ ``` -## Summary +## Tổng kết -- Constructor functions or, briefly, constructors, are regular functions, but there's a common agreement to name them with capital letter first. -- Constructor functions should only be called using `new`. Such a call implies a creation of empty `this` at the start and returning the populated one at the end. +- Constructor functions hay ngắn gọn là constructors, là một hàm bình thường như bao hàm khác. Nhưng theo quy ước nên đặt tên có chữ cái đầu tiên được viết hoa. +- Constructor được gọi với toán tử `new`. Nó sẽ tạo ra một object rỗng {} và gán cho `this` thực hiện phần thân hàm và trả về `this`. -We can use constructor functions to make multiple similar objects. +Ta sử dụng Constructer để tạo ra các objects tương tự nhau. -JavaScript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study. +JavaScript có sẵn một số constructer như: `Date`, `Set` (học sau). -```smart header="Objects, we'll be back!" -In this chapter we only cover the basics about objects and constructors. They are essential for learning more about data types and functions in the next chapters. +```smart header="Objects, ta sẽ quay trở lại!" +Chương này ta học cơ bản về object và constructer thôi. Nó cần thiết cho việc học các chương tiếp theo. -After we learn that, in the chapter we return to objects and cover them in-depth, including inheritance and classes. +Sau đó ta quay trở lại và học thêm sâu hơn với *kế thừa* và Classes. ``` From fca7cbd76db442286539b1a5a3f4ae50184ddfed Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 7 Nov 2017 17:46:04 +0700 Subject: [PATCH 71/78] Update article.md --- .../01-primitives-methods/article.md | 90 +++++++++---------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/1-js/05-data-types/01-primitives-methods/article.md b/1-js/05-data-types/01-primitives-methods/article.md index e822190750..2078711652 100644 --- a/1-js/05-data-types/01-primitives-methods/article.md +++ b/1-js/05-data-types/01-primitives-methods/article.md @@ -1,20 +1,18 @@ -# Methods of primitives +# Methods của primitives -JavaScript allows us to work with primitives (strings, numbers etc) as if they were objects. +JavaScript cho phép làm việc với primitives (strings, numbers ..) như kiểu chúng là objects. -They also provide methods to call and such. We will study those soon, but first we'll see how it works, because, of course, primitives are not objects (and here we will make it even more clear). +Nó cung cấp các method có thể gọi được trên primitives, chúng ta sẽ học ngay bây giờ, nhưng chúng ta sẽ xem xét tại sao lại như thế. Bởi dù sao primitive không phải là objects. [cut] -Let's look at the key distinction between primitives and objects. +Chúng ta cùng phân biệt những điểm chính giữa primitives và objects. -A primitive +Một object +: có khả năng lưu trữ nhiều giá trị trong các properties. +Có thể được tạo ra bằng cách `{}`, Ví dụ: `{name: "John", age: 30}`. Có nhiều kiểu Object khác trong JavaScript, Ví dụ. functions là objects. -An object -: Is capable of storing multiple values as properties. -Can be created with `{}`, for instance: `{name: "John", age: 30}`. There are other kinds of objects in JavaScript, e.g. functions are objects. - -One of the best things about objects is that we can store a function as one of its properties: +Một trong những điều hay nhất về objects là ta có thể lưu một hàm vào properties: ```js run let john = { @@ -27,32 +25,32 @@ let john = { john.sayHi(); // Hi buddy! ``` -So here we've made an object `john` with the method `sayHi`. +Ở đây ta tạo ra object `john` với method `sayHi`. -Many built-in objects already exist, such as those that work with dates, errors, HTML elements etc. They have different properties and methods. +Một vài Object built-in có sẵn trong JS, ví dụ dates, errors, HTML elements ... Nó có các properties và methods khác nhau. -But, these features come with a cost! +Nhưng, các tính năng đó đều phải trả giá! -Objects are "heavier" than primitives. They require additional resources to support the internal machinery. But as properties and methods are very useful in programming, JavaScript engines try to optimize them to reduce the additional burden. +Objects nặng hơn primitives, chúng chiếm nhiều tài nguyên hệ thống hơn. Nhưng chúng lại rất hữu ích trong lập trình, JavaScript engines đang cố gắng cải thiện chúng, để giảm sự tiêu tốn về tài nguyên hệ thống. -## A primitive as an object +## Một primitive là một object -Here's the paradox faced by the creator of JavaScript: +Đây là nghịch lý trong JavaScript: -- There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods. -- Primitives must be as fast and lightweight as possible. +- Có vài thứ ta muốn làm với primitive, và những việc đó sẽ dễ dàng hơn nếu có sẵn các method. +- Primitives phải nhanh và nhẹ như chúng vốn có. -The solution looks a little bit awkward, but here it is: +Và giải pháp là: -1. Primitives are still primitive. A single value, as desired. -2. The language allows access to methods and properties of strings, numbers, booleans and symbols. -3. When this happens, a special "object wrapper" is created that provides the extra functionality, and then is destroyed. +1. Primitives vẫn là primitive. Một giá trị đơn như mong muốn. +2. JS cho phép truy cập các methods và properties của strings, numbers, booleans và symbols. +3. Khi điều này xảy ra một "object tạm thời - object wrapper" được tạo ra cung cấp chức năng này, sau đó nó được xóa đi. -The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean` and `Symbol`. Thus, they provide different sets of methods. +"Object wrappers" khác nhau cho mỗi loại primitive, gồm: `String`, `Number`, `Boolean` và `Symbol`. Như vậy chúng cũng cung cấp các methods khác nhau. -For instance, there exists a method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns a capitalized string. +Ví dụ, có method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) trả về một string được viết hoa. -Here's how it works: +Như này: ```js run let str = "Hello"; @@ -60,17 +58,17 @@ let str = "Hello"; alert( str.toUpperCase() ); // HELLO ``` -Simple, right? Here's what actually happens in `str.toUpperCase()`: +Đây là những gì xảy ra khi ta gọi `str.toUpperCase()`: -1. The string `str` is a primitive. So in the moment of accessing its property, a special object is created that knows the value of the string, and has useful methods, like `toUpperCase()`. -2. That method runs and returns a new string (shown by `alert`). -3. The special object is destroyed, leaving the primitive `str` alone. +1. Chuỗi `str` là một primitive. Vì vậy khi ta truy cập property của nó, một object tạm thời được tạo ra, với những method hữu ích như `toUpperCase()`. +2. Gọi method này, nó chạy và trả về chuỗi `str` được viết hoa. +3. Object tạm bị xóa, để lại primitive `str` như ban đầu. -So primitives can provide methods, but they still remain lightweight. +Vì vậy primitives có thể cung cấp các methods, nhưng chúng nhẹ hơn. -The JavaScript engine highly optimizes this process. It may even skip the creation of the extra object at all. But it must still adhere to the specification and behave as if it creates one. +JavaScript engine đã và đang cải thiện rất nhiều quá trình này. Nó thậm chí không tạo ra Object tạm như đã nói, tuy nhiên ở đây ta vẫn đề cập đến cho dễ hiểu. -A number has methods of its own, for instance, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to the given precision: +Number có các method của nó, ví dụ, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) để làm tròn số: ```js run let n = 1.23456; @@ -78,15 +76,15 @@ let n = 1.23456; alert( n.toFixed(2) ); // 1.23 ``` -We'll see more specific methods in chapters and . +Ta sẽ học nhiều về các method của string, number ở bài . -````warn header="Constructors `String/Number/Boolean` are for internal use only" -Some languages like Java allow us to create "wrapper objects" for primitives explicitly using a syntax like `new Number(1)` or `new Boolean(false)`. +````warn header="Constructors `String/Number/Boolean` chỉ được dùng nội bộ" +các NNLT khác như Java tạo ra "wrapper objects" cho primitives một cách rõ ràng bởi cú pháp `new Number(1)` hoặc `new Boolean(false)`. -In JavaScript, that's also possible for historical reasons, but highly **unrecommended**. Things will go crazy in several places. +Trong JavaScript, cũng có thể, Nhưng **không được khuyến khích**. Chúng dành cho một số thứ quái đản khác. -For instance: +Ví dụ: ```js run alert( typeof 1 ); // "number" @@ -94,7 +92,7 @@ alert( typeof 1 ); // "number" alert( typeof new Number(1) ); // "object"! ``` -And because what follows, `zero`, is an object, the alert will show up: +Và, `zero`, là một object, nên: ```js run let zero = new Number(0); @@ -104,25 +102,25 @@ if (zero) { // zero is true, because it's an object } ``` -On the other hand, using the same functions `String/Number/Boolean` without `new` is a totally sane and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive). +Sử dụng hàm `String/Number/Boolean` không có `new` cho một số thứ hữu dụng. chúng convert giá trị sang kiểu: string, number, hoặc boolean (primitive). -For example, this is entirely valid: +Ví dụ: ```js let num = Number("123"); // convert a string to number ``` ```` -````warn header="null/undefined have no methods" -The special primitives `null` and `undefined` are exceptions. They have no corresponding "wrapper objects" and provide no methods. In a sense, they are "the most primitive". +````warn header="null/undefined không có methods" +Kiểu primitives đặc biệt `null` và `undefined` là ngoại lệ. Chúng không có "wrapper objects" tương ứng và không cung cấp các methods. Trong một ngữ nghĩa nào đó chúng là "the most primitive - nguyên thủy nhất". -An attempt to access a property of such value would give the error: +VD: ```js run alert(null.test); // error ```` -## Summary +## Tổng kết -- Primitives except `null` and `undefined` provide many helpful methods. We will study those in the upcoming chapters. -- Formally, these methods work via temporary objects, but JavaScript engines are well tuned to optimize that internally, so they are not expensive to call. +- Primitives ngoại trừ `null` và `undefined` cung cấp một số methods hữu ích. Ta sẽ học sau. +- Chính thức, các method này hoạt động thông qua các object tạm thời, Nhưng JavaScript engines đang tối ưu hết sức, nên sẽ không tiêu tốn tài nguyên cho lắm khi sử dụng chúng. From e1b50beb0cd661c03d23cf0800e23ecd7bd3faa6 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 7 Nov 2017 20:15:58 +0700 Subject: [PATCH 72/78] Update article.md --- 1-js/05-data-types/02-number/article.md | 128 ++++++++++++------------ 1 file changed, 62 insertions(+), 66 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 16e4275e60..539faf9cfb 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -1,20 +1,20 @@ # Numbers -All numbers in JavaScript are stored in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), also known as "double precision". +Tất cả số trong JavaScript được lưu trữ dưới dạng 64-bit [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985). -Let's recap and expand upon what we currently know about them. +Chúng ta hãy tóm tắt lại và mở rộng những gì chúng ta biết về chúng. -## More ways to write a number +## Nhiều cách để viết một number -Imagine we need to write 1 billion. The obvious way is: +Giả sử với số 1 tỷ, thường ta viết: ```js let billion = 1000000000; ``` -But in real life we usually avoid writing a long string of zeroes as it's easy to mistype. Also, we are lazy. We will usually write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers. +Trong thực tế thì viết như thế hay bị nhầm, và chúng ta cũng rất lười khi viết dài như vậy. -In JavaScript, we shorten a number by appending the letter `"e"` to the number and specifying the zeroes count: +Trong JavaScript, ta có thể viết ngắn hơn bằng cách sử dụng chữ `"e"`: ```js run let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes @@ -22,7 +22,7 @@ let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes alert( 7.3e9 ); // 7.3 billions (7,300,000,000) ``` -In other words, `"e"` multiplies the number by `1` with the given zeroes count. +`"e"` ở đây chính là `nhân với 10 mũ e`. ```js 1e3 = 1 * 1000 @@ -30,21 +30,19 @@ In other words, `"e"` multiplies the number by `1` with the given zeroes count. ``` -Now let's write something very small. Say, 1 microsecond (one millionth of a second): +`e` có thể là một số âm, ví dụ khi biểu diễn một mili giây: ```js let ms = 0.000001; ``` -Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say: +Sử dụng `e`: ```js let ms = 1e-6; // six zeroes to the left from 1 ``` -If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`. - -In other words, a negative number after `"e"` means a division by 1 with the given number of zeroes: +Nói cách khác, khi `e` âm có nghĩa là chia cho `10 mũ |e|`: ```js // -3 divides by 1 with 3 zeroes @@ -54,18 +52,18 @@ In other words, a negative number after `"e"` means a division by 1 with the giv 1.23e-6 = 1.23 / 1000000 (=0.00000123) ``` -### Hex, binary and octal numbers - -[Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) numbers are widely used in JavaScript to represent colors, encode characters, and for many other things. So naturally, there exists a shorter way to write them: `0x` and then the number. +### Hex, binary và octal numbers + +Số [Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) (thập lục phân) thường biểu diễn màu sắc, mã hóa ký tự... So naturally, cách viết một số Hexa là bắt đầu bằng: `0x` và sau đó là số. -For instance: +Ví dụ: ```js run alert( 0xff ); // 255 alert( 0xFF ); // 255 (the same, case doesn't matter) ``` -Binary and octal numeral systems are rarely used, but also supported using the `0b` and `0o` prefixes: +Số Binary (nhị phân) và octal (bát phân) ít khi được sử dụng, chúng bắt đầu bằng tiền tố `0b` và `0o`: ```js run @@ -75,13 +73,13 @@ let b = 0o377; // octal form of 255 alert( a == b ); // true, the same number 255 at both sides ``` -There are only 3 numeral systems with such support. For other numeral systems, we should use the function `parseInt` (which we will see later in this chapter). +Nếu cần viết dưới dạng cơ số khác, ta dùng `parseInt` (sẽ học tới trong bài này). ## toString(base) -The method `num.toString(base)` returns a string representation of `num` in the numeral system with the given `base`. +Method `num.toString(base)` trả về một chuỗi là số `num` viết trong cơ số `base`. -For example: +Ví dụ: ```js run let num = 255; @@ -89,45 +87,43 @@ alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111 ``` -The `base` can vary from `2` to `36`. By default it's `10`. +Cơ số `base` có thể có giá trị từ `2` đến `36`. Giá trị mặc định là `10`. -Common use cases for this are: +Các cơ số hay được sử dụng là: -- **base=16** is used for hex colors, character encodings etc, digits can be `0..9` or `A..F`. -- **base=2** is mostly for debugging bitwise operations, digits can be `0` or `1`. -- **base=36** is the maximum, digits can be `0..9` or `A..Z`. The whole latin alphabet is used to represent a number. A funny, but useful case for `36` is when we need to turn a long numeric identifier into something shorter, for example to make a short url. Can simply represent it in the numeral system with base `36`: +- **base=16** cho màu sắc, mã hóa ký tự...được dùng các chữ số từ `0..9` và `A..F`. +- **base=2** được dùng với các phép toán nhị phân, chỉ dùng hai chữ số `0` và `1`. +- **base=36** là lớn nhất, được dùng các chữ số từ `0..9` và `A..Z`. Các chữ cái latin được dùng để biểu diễn một số. Thường dùng khi cần biễu diễn một chuỗi số dài một cách ngắn hơn: ```js run alert( 123456..toString(36) ); // 2n9c ``` -```warn header="Two dots to call a method" -Please note that two dots in `123456..toString(36)` is not a typo. If we want to call a method directly on a number, like `toString` in the example above, then we need to place two dots `..` after it. +```warn header="Hai dấu chấm để gọi method" +Chú ý dùng hai dấu chấm `123456..toString(36)` không phải là lỗi đánh máy. Khi gọi một method từ number, như `toString` trong ví dụ trên thì cần sử dụng hai dấu chấm `..`. -If we placed a single dot: `123456.toString(36)`, then there would be an error, because JavaScript syntax implies the decimal part after the first dot. And if we place one more dot, then JavaScript knows that the decimal part is empty and now goes the method. +Nếu dùng một dấu chấm: `123456.toString(36)` sẽ lỗi, bởi vì cú pháp JavaScript dùng một dấu chấm với ý nghĩa đó là phần thập phân. Và thêm một dấu chấm nữa, thì JavaScript biết rằng là không có phần thập phân và ta đang gọi method. -Also could write `(123456).toString(36)`. +Cũng có thể viết `(123456).toString(36)`. ``` -## Rounding - -One of the most used operations when working with numbers is rounding. +## Làm tròn -There are several built-in functions for rounding: +Đã có một hàm built-in cho việc làm tròn số: `Math.floor` -: Rounds down: `3.1` becomes `3`, and `-1.1` becomes `-2`. +: Làm tròn dưới: `3.1` trở thành `3`, và `-1.1` trở thành `-2`. `Math.ceil` -: Rounds up: `3.1` becomes `4`, and `-1.1` becomes `-1`. +: Làm tròn trên: `3.1` trở thành `4`, và `-1.1` trở thành `-1`. `Math.round` -: Rounds to the nearest integer: `3.1` becomes `3`, `3.6` becomes `4` and `-1.1` becomes `-1`. +: Làm tròn đến giá trị gần nhất: `3.1` trở thành `3`, `3.6` trở thành `4` và `-1.1` trở thành `-1`. -`Math.trunc` (not supported by Internet Explorer) -: Removes anything after the decimal point without rounding: `3.1` becomes `3`, `-1.1` becomes `-1`. +`Math.trunc` (ko hỗ trợ trên trình duyệt Internet Explorer) +: Bõ phần thập phân: `3.1` trở thành `3`, `-1.1` trở thành `-1`. -Here's the table to summarize the differences between them: +Bảng tóm tắt: | | `Math.floor` | `Math.ceil` | `Math.round` | `Math.trunc` | |---|---------|--------|---------|---------| @@ -137,94 +133,94 @@ Here's the table to summarize the differences between them: |`-1.6`| `-2` | `-1` | `-2` | `-1` | -These functions cover all of the possible ways to deal with the decimal part of a number. But what if we'd like to round the number to `n-th` digit after the decimal? +Những hàm trên chỉ làm tròn thành số nguyên, nếu muốn làm tròn đến số thập phân thứ `n-th` ta phải làm sao? -For instance, we have `1.2345` and want to round it to 2 digits, getting only `1.23`. +Ví dụ làm tròn `1.2345` với 2 chữ số thập phân, trở thành `1.23`. -There are two ways to do so: +Có hai cách: -1. Multiply-and-divide. +1. Nhân và chia. - For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100`, call the rounding function and then divide it back. + Ví dụ làm tròn hai chữ số, ta nhân với `100`, rồi lại chia cho `100`. ```js run let num = 1.23456; alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23 ``` -2. The method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to `n` digits after the point and returns a string representation of the result. +2. Method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) làm tròn số đến `n` chữ số thập phân, biểu diễn thành một string chưa số đó. ```js run let num = 12.34; alert( num.toFixed(1) ); // "12.3" ``` - This rounds up or down to the nearest value, similar to `Math.round`: + Tất cả các phép làm tròn, như `Math.round`: ```js run let num = 12.36; alert( num.toFixed(1) ); // "12.4" ``` - Please note that result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end: + Chú ý, kết quả của phép `toFixed` là một string. Nếu phần thập hơn có ít chữ số hơn cần thiết, các số `0` sẽ được điền vào: ```js run let num = 12.34; alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits ``` - We can convert it to a number using the unary plus or a `Number()` call: `+num.toFixed(5)`. + Ta có thể convert thành số bởi `Number()` hoặc `+num.toFixed(5)`. -## Imprecise calculations +## Sự tính toán không chính xác. -Internally, a number is represented in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign. +Number được biểu diễn dưới dạng 64-bit [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), nên có chính xác 64 bit để lưu trữ một number: 52 bits để lưu các chữ số, 11 bits để lưu trữ các số sau dấu chấm thập phân (chúng = "0" nếu là số nguyên), và 1 bit cho dấu (âm hoặc dương). -If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity: +Nếu số quá lớn, nó sẽ tràn 64-bit bộ nhớ, có khả năng cho ra một số infinity: ```js run alert( 1e500 ); // Infinity ``` -What may be a little less obvious, but happens quite often, is the loss of precision. +Có một việc xảy ra khá thường xuyên, là mất chính xác trong các phép tính. -Consider this (falsy!) test: +Ví dụ: ```js run alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!* ``` -That's right, if we check whether the sum of `0.1` and `0.2` is `0.3`, we get `false`. +Đúng vậy, `0.1` cộng `0.2` không phải là `0.3`. -Strange! What is it then if not `0.3`? +Thật kỳ là, vậy kết quả là gì nếu không phải là `0.3`? ```js run alert( 0.1 + 0.2 ); // 0.30000000000000004 ``` -Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into his chart. The order total will be `$0.30000000000000004`. That would surprise anyone. +Có nhiều hậu quả cho sự sai lệch này. Hãy tưởng tượng bạn có trang web bán hàng, khách hàng mua `$0.10` và `$0.20` hàng. Tổng cộng sẽ là `$0.30000000000000004`. Thật ngạc nhiên đúng không -But why does this happen? +Nhưng tại sao nó lại xảy ra? -A number is stored in memory in its binary form, a sequence of ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form. +Một number được lưu trữ dưới dạng các bít, một chuỗi số 0 và 1. Nhưng các phân số như `0.1`, `0.2` trong có vẽ đơn giản trong cơ số thập phân. Nhưng lại vô hạn trong phân số hay biễu diễn nhị phân. -In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`. +Nói cách khác, `0.1` là gì? nó là 1 chia cho 10 `1/10`. Trong hệ số thập phân, các số như vậy là rất dễ dàng biểu diễn. So sánh chúng với: `1/3`. Nó là một số thập phân vô hạn `0.33333(3)`. -So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction. +Cho nên, phép chia cho `10` luôn bảo đảm hoạt động đúng trong hệ thập phân, nhưng phép chia cho `3` thì không. Cùng một lý do, trong hệ nhị phân, phép chia cho `2` luôn hoạt động đúng, nhưng `1/10` là một số vô hạn. -There's just no way to store *exactly 0.1* or *exactly 0.2* using the binary system, just like there is no way to store one-third as a decimal fraction. +Không có cách nào để lưu trữ chính xác giá trị `0.1` hoặc `0.2`, giống như việc không có cách nào lưu trữ chính xác giá trị `1/3` trong hệ thập phân. -The numeric format IEEE-754 solves this by rounding to the nearest possible number. These rounding rules normally don't allow us to see that "tiny precision loss", so the number shows up as `0.3`. But beware, the loss still exists. +Định dạng số IEEE-754 giải quyết vấn đề này bằng cách làm tròn số. Phép làm tròn thông thường không show ra những sai số nhỏ bé, nên kết quả show ra là `0.3`. Nhưng hãy cẩn thận, kết quả có một sai số rất nhỏ. -We can see this in action: +Chúng ta có thể xem ví dụ sau đây: ```js run alert( 0.1.toFixed(20) ); // 0.10000000000000000555 ``` -And when we sum two numbers, their "precision losses" add up. +Khi chúng ta cộng hai số, các sai số nhỏ bé này cũng được cộng vào. -That's why `0.1 + 0.2` is not exactly `0.3`. +Đó là tại sao `0.1 + 0.2` không có kết quả chính xác là `0.3`. -```smart header="Not only JavaScript" +```smart header="Không phải chỉ có JavaScript" The same issue exists in many other programming languages. PHP, Java, C, Perl, Ruby give exactly the same result, because they are based on the same numeric format. From 0e6dbd73b671eed7a68caff4f07afd3f258781ed Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 7 Nov 2017 22:20:31 +0700 Subject: [PATCH 73/78] Update article.md --- 1-js/05-data-types/02-number/article.md | 123 ++++++++++++------------ 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 539faf9cfb..b849d14056 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -221,84 +221,82 @@ Khi chúng ta cộng hai số, các sai số nhỏ bé này cũng được cộn Đó là tại sao `0.1 + 0.2` không có kết quả chính xác là `0.3`. ```smart header="Không phải chỉ có JavaScript" -The same issue exists in many other programming languages. +Vấn đề này cũng xảy ra trong các NNLT khác. -PHP, Java, C, Perl, Ruby give exactly the same result, because they are based on the same numeric format. +PHP, Java, C, Perl, Ruby cũng có cùng vấn đề vì chúng định dạng Number theo các tương tự. ``` -Can we work around the problem? Sure, there're a number of ways: +Chúng ta có thể làm việc được với vấn đề này ? chắc rồi, có một số cách: -1. We can round the result with the help of a method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed): +1. Ta làm tròn số với method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed): ```js run let sum = 0.1 + 0.2; alert( sum.toFixed(2) ); // 0.30 ``` - Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number: + Chú ý rằng `toFixed` trả về một string. Nó đảm bảo rằng trả về đúng 2 chữ số phần thập phân cho ví dụ ở trên. Đó chính là những gì ta cần với trường hợp shop bán hàng online, `$0.30`. Với những trường hợp cần number, thêm dấu + đằng trước để convert sang number: ```js run let sum = 0.1 + 0.2; alert( +sum.toFixed(2) ); // 0.3 ``` -2. We can temporarily turn numbers into integers for the maths and then revert it back. It works like this: +2. Đưa về dạng số nguyên để tính toán, sau đó lại trả kết quả về dạng thập phân: ```js run alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3 ``` - This works because when we do `0.1 * 10 = 1` and `0.2 * 10 = 2` then both numbers become integers, and there's no precision loss. - -3. If we were dealing with a shop, then the most radical solution would be to store all prices in cents and use no fractions at all. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely feasible, so the solutions above help avoid this pitfall. + Nó hoạt động vì `0.1 * 10 = 1` và `0.2 * 10 = 2` là hai số nguyên, sẽ không có sai số. ````smart header="The funny thing" -Try running this: +Chạy dòng code dưới: ```js run // Hello! I'm a self-increasing number! alert( 9999999999999999 ); // shows 10000000000000000 ``` -This suffers from the same issue: a loss of precision. There are 64 bits for the number, 52 of them can be used to store digits, but that's not enough. So the least significant digits disappear. +Đây cũng là một vấn đề tương tự: Sai số. 64 bits cho number, 52 bits để lưu giá trị, với các số quá lớn là không đủ. Cho nên các chữ số không quan trọng sẽ bị bõ qua -JavaScript doesn't trigger an error in such events. It does its best to fit the number into the desired format, but unfortunately, this format is not big enough. +JavaScript sẽ không báo lỗi. Nó sẽ đưa về theo định dạng số đã mô tả. Nhưng, định dạng này không đủ lớn. ```` -```smart header="Two zeroes" -Another funny consequence of the internal representation of numbers is the existence of two zeroes: `0` and `-0`. +```smart header="Hai số `0`" +Có một cái funny nữa là có hai số không: `0` và `-0`. -That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero. +Ta đã biết có một bits để lưu dấu của số, nên ta có các số đều có số âm và số dương, bao gồm cẩ số `0`. -In most cases the distinction is unnoticeable, because operators are suited to treat them as the same. +Trong nhiều trường hợp sự phân biệt này là không đáng nhắc đến vì phép toán sẽ cho ra cùng một kết quả. ``` -## Tests: isFinite and isNaN +## Kiểm tra: isFinite và isNaN -Remember these two special numeric values? +Có nhớ hai số đặc biệt không? -- `Infinite` (and `-Infinite`) is a special numeric value that is greater (less) than anything. -- `NaN` represents an error. +- `Infinity` (và `-Infinity`) là vô cực nó lớn hơn (nhỏ hơn) bất kỳ số nào. +- `NaN` đại diện cho lỗi. -They belong to the type `number`, but are not "normal" numbers, so there are special functions to check for them: +Chúng là một `number`, nhưng không "bình thường", cho nên có hàm để kiểm tra: -- `isNaN(value)` converts its argument to a number and then tests it for being `NaN`: +- `isNaN(value)` convert tham số sang number và xem có phải là `NaN` hay không: ```js run alert( isNaN(NaN) ); // true alert( isNaN("str") ); // true ``` - But do we need this function? Can't we just use the comparison `=== NaN`? Sorry, but the answer is no. The value `NaN` is unique in that it does not equal anything, including itself: + Chúng ta có cần hàm này không? ta có thể dùng phép so sánh `=== NaN`? Không được nhé vì `NaN` là duy nhất và nó không bằng thằng nào hết, bao gồm chính nó: ```js run alert( NaN === NaN ); // false ``` -- `isFinite(value)` converts its argument to a number and returns `true` if it's a regular number, not `NaN/Infinity/-Infinity`: +- `isFinite(value)` converts tham số thành number, trả về `true` nếu là một số bình thường, không phải `NaN/Infinity/-Infinity`: ```js run alert( isFinite("15") ); // true @@ -306,7 +304,7 @@ They belong to the type `number`, but are not "normal" numbers, so there are spe alert( isFinite(Infinity) ); // false, because a special value: Infinity ``` -Sometimes `isFinite` is used to validate whether a string value is a regular number: +Thỉnh thoảng `isFinite` để dùng để xác nhận một string có phải là một số bình thường hay không: ```js run @@ -316,36 +314,36 @@ let num = +prompt("Enter a number", ''); alert( isFinite(num) ); ``` -Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`. +Chú ý string rỗng hoặc chỉ gồm các dấu space là `0` trong tất cả các hàm số học, bao gồm cả `isFinite`. -```smart header="Compare with `Object.is`" +```smart header="So sánh với `Object.is`" -There is a special built-in method [Object.is](mdn:js/Object/is) that compares values like `===`, but is more reliable for two edge cases: +Là một built-in method [Object.is](mdn:js/Object/is) so sánh giá trị với `===`, nhưng tin cậy hơn vì hai trường hợp biên: -1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing. -2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, it rarely matters, but these values technically are different. +1. Hoạt động với `NaN`: `Object.is(NaN, NaN) === true`, Rất tốt. +2. Giá trị `0` và `-0` là khác nhau: `Object.is(0, -0) === false`, mặc dù hiếm khi dùng, nhưng về mặt kỹ thuật thì đúng là như thế. -In all other cases, `Object.is(a, b)` is the same as `a === b`. +Còn lại tất cả các trường hợp khác, `Object.is(a, b)` là tương đương với `a === b`. -This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). +Cách so sánh nay được JavaScript sử dụng rất nhiều trong các tính năng của nó. `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). ``` -## parseInt and parseFloat +## parseInt và parseFloat -Numeric conversion using a plus `+` or `Number()` is strict. If a value is not exactly a number, it fails: +Conver qua number sử dụng `+` hoặc `Number()` là nghiêm ngặt. Nếu giá trị không chính xác hoàn toàn là số, nó sẽ fail: ```js run alert( +"100px" ); // NaN ``` -The sole exception is spaces at the beginning or at the end of the string, as they are ignored. +Ngoại lệ duy nhất là các dấu space ở đầu hoặc cuối chuỗi, vì nó sẽ bị bõ qua. -But in real life we often have values in units, like `"100px"` or `"12pt"` in CSS. Also in many countries the currency symbol goes after the amount, so we have `"19€"` and would like to extract a numeric value out of that. +Trong thực tế ta có nhiều giá trị dạng `"100px"` hoặc `"12pt"` trong CSS. Hay tiền tệ của các nước sẽ có ký hiệu đằng sau như `"19€"` cần một cách để convert các giá trị dạng này ra số. -That's what `parseInt` and `parseFloat` are for. +Đó là tác dụng của `parseInt` và `parseFloat` được dùng. -They "read" a number from a string until they can. In case of an error, the gathered number is returned. The function `parseInt` returns an integer, whilst `parseFloat` will return a floating-point number: +Chúng đọc các số đầu tiên trong một chuỗi. Hàm `parseInt` trả về integer, `parseFloat` trả về số dấu chấm động: ```js run alert( parseInt('100px') ); // 100 @@ -355,14 +353,14 @@ alert( parseInt('12.3') ); // 12, only the integer part is returned alert( parseFloat('12.3.4') ); // 12.3, the second point stops the reading ``` -There are situations when `parseInt/parseFloat` will return `NaN`. It happens when no digits could be read: +Các tình huống `parseInt/parseFloat` trả về `NaN`: ```js run alert( parseInt('a123') ); // NaN, the first symbol stops the process ``` -````smart header="The second argument of `parseInt(str, radix)`" -The `parseInt()` function has an optional second parameter. It specifies the base of the numeral system, so `parseInt` can also parse strings of hex numbers, binary numbers and so on: +````smart header="Tham số thứ hai trong `parseInt(str, radix)`" +Hàm `parseInt()` có một tham số tùy chọn. thể hiện cơ số, nên `parseInt` có thể convert sang hex numbers, binary numbers ...: ```js run alert( parseInt('0xff', 16) ); // 255 @@ -372,14 +370,14 @@ alert( parseInt('2n9c', 36) ); // 123456 ``` ```` -## Other math functions +## Một số hàm toán học khác -JavaScript has a built-in [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object which contains a small library of mathematical functions and constants. +JavaScript có object built-in [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) bao gồm một thư viện các hàm toán học và hằng số. -A few examples: +Một vài ví dụ: `Math.random()` -: Returns a random number from 0 to 1 (not including 1) +: Trả về một số ngẫu nhiên từ `0` tới `1` (không bao gồm 1) ```js run alert( Math.random() ); // 0.1234567894322 @@ -388,7 +386,7 @@ A few examples: ``` `Math.max(a, b, c...)` / `Math.min(a, b, c...)` -: Returns the greatest/smallest from the arbitrary number of arguments. +: Trả về giá trị lớn nhất / nhỏ nhất trong các tham số. ```js run alert( Math.max(3, 5, -10, 0, 1) ); // 5 @@ -396,38 +394,37 @@ A few examples: ``` `Math.pow(n, power)` -: Returns `n` raised the given power +: hàm mũ ```js run alert( Math.pow(2, 10) ); // 2 in power 10 = 1024 ``` -There are more functions and constants in `Math` object, including trigonometry, which you can find in the [docs for the Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object. +Có nhiều hàm và hằng số toán học trong `Math` object xem thêm tại (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object. -## Summary +## Tổng kết -To write big numbers: +Để viết một số lớn: -- Append `"e"` with the zeroes count to the number. Like: `123e6` is `123` with 6 zeroes. -- A negative number after `"e"` causes the number to be divided by 1 with given zeroes. That's for one-millionth or such. +- Dùng `"e"` ví dụ: `123e6` là `123000000` , `123e-3` là 0.123 . -For different numeral systems: +Trong các hệ cơ số khác nhau: -- Can write numbers directly in hex (`0x`), octal (`0o`) and binary (`0b`) systems -- `parseInt(str, base)` parses an integer from any numeral system with base: `2 ≤ base ≤ 36`. -- `num.toString(base)` converts a number to a string in the numeral system with the given `base`. +- hex (`0x`), octal (`0o`) và binary (`0b`) +- `parseInt(str, base)` biểu diễn một str số nguyên theo cơ số base: `2 ≤ base ≤ 36`. +- `num.toString(base)` converts một số sang string là số theo cơ số `base`. -For converting values like `12pt` and `100px` to a number: +Conver các giá trị dạng `12pt` và `100px` sang số: -- Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error. +- Dùng `parseInt/parseFloat` -For fractions: +Cho phân số: -- Round using `Math.floor`, `Math.ceil`, `Math.trunc`, `Math.round` or `num.toFixed(precision)`. -- Make sure to remember there's a loss of precision when working with fractions. +- Làm tròn sử dụng `Math.floor`, `Math.ceil`, `Math.trunc`, `Math.round` hoặc `num.toFixed(precision)`. +- Chú ý sai số. -More mathematical functions: +Một số hàm toán học khác: -- See the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object when you need them. The library is very small, but can cover basic needs. +- Xem thêm Object [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math). From 912f20bb2d5ad24976a336a09a52c1b5446669fd Mon Sep 17 00:00:00 2001 From: Son Tran Date: Wed, 8 Nov 2017 22:25:49 +0700 Subject: [PATCH 74/78] Update article.md --- 1-js/05-data-types/03-string/article.md | 259 +++++++++++------------- 1 file changed, 123 insertions(+), 136 deletions(-) diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md index dfa2fc25c5..78cf842784 100644 --- a/1-js/05-data-types/03-string/article.md +++ b/1-js/05-data-types/03-string/article.md @@ -1,16 +1,14 @@ # Strings -In JavaScript, the textual data is stored as strings. There is no separate type for a single character. +Trong JavaScript, dữ liệu văn bản được lưu trữ dưới dạng strings. Kể cả các chữ cái đơn. -The internal format for strings is always [UTF-16](https://en.wikipedia.org/wiki/UTF-16), it is not tied to the page encoding. +Định dạng string luôn là kiểu [UTF-16](https://en.wikipedia.org/wiki/UTF-16), Nó không gắn liền với mã hóa trang web. [cut] ## Quotes -Let's recall the kinds of quotes. - -Strings can be enclosed within either single quotes, double quotes or backticks: +String được bao quanh bởi cặp dấu nháy đơn - single quotes hoặc nháy kép - double quotes hoặc backticks: ```js let single = 'single-quoted'; @@ -19,7 +17,7 @@ let double = "double-quoted"; let backticks = `backticks`; ``` -Single and double quotes are essentially the same. Backticks however allow us to embed any expression into the string, including function calls: +Single và double quotes là như nhau. Backticks là một template cho phép ta nhúng biến, biểu thức vào, bao gồm cả gọi hàm: ```js run function sum(a, b) { @@ -29,7 +27,7 @@ function sum(a, b) { alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3. ``` -Another advantage of using backticks is that they allow a string to span multiple lines: +Sử dụng backticks cũng cho phép viết String trên nhiều dòng: ```js run let guestList = `Guests: @@ -41,20 +39,19 @@ let guestList = `Guests: alert(guestList); // a list of guests, multiple lines ``` -If we try to use single or double quotes in the same way, there will be an error: +Nếu dùng single hoặc double quotes như ví dụ bên trên sẽ báo lỗi: ```js run let guestList = "Guests: // Error: Unexpected token ILLEGAL * John"; ``` -Single and double quotes come from ancient times of language creation when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile. -Backticks also allow us to specify a "template function" before the first backtick. The syntax is: func`string`. The function `func` is called automatically, receives the string and embedded expressions and can process them. You can read more about it in the [docs](mdn:JavaScript/Reference/Template_literals#Tagged_template_literals). This is called "tagged templates". This feature makes it easier to wrap strings into custom templating or other functionality, but it is rarely used. +Backticks cũng cho phép ta sử dụng "template function" . Cú pháp: func`string`. Hàm `func` được gọi, nhận string và biểu thức được nhúng vào, sau đó xử lý chúng. Có thể tìm hiểu thêm tại [docs](mdn:JavaScript/Reference/Template_literals#Tagged_template_literals). Cái này được gọi là "tagged templates". Tính năng này cũng hiếm khi được sử dụng. -## Special characters +## Các ký tự đặc biệt -It is still possible to create multiline strings with single quotes by using a so-called "newline character", written as `\n`, which denotes a line break: +Ký tự `\n` đại diện cho xuống hàng: ```js run let guestList = "Guests:\n * John\n * Pete\n * Mary"; @@ -62,7 +59,7 @@ let guestList = "Guests:\n * John\n * Pete\n * Mary"; alert(guestList); // a multiline list of guests ``` -For example, these two lines describe the same: +Ví dụ viết String trên 2 hàng bằng hai cách: ```js run alert( "Hello\nWorld" ); // two lines using a "newline symbol" @@ -72,7 +69,7 @@ alert( `Hello World` ); ``` -There are other, less common "special" characters as well. Here's the list: +Một vài ký tự đặc biệt khác: | Character | Description | |-----------|-------------| @@ -81,10 +78,10 @@ There are other, less common "special" characters as well. Here's the list: |`\n`|New line| |`\r`|Carriage return| |`\t`|Tab| -|`\uNNNN`|A unicode symbol with the hex code `NNNN`, for instance `\u00A9` -- is a unicode for the copyright symbol `©`. It must be exactly 4 hex digits. | -|`\u{NNNNNNNN}`|Some rare characters are encoded with two unicode symbols, taking up to 4 bytes. This long unicode requires braces around it.| +|`\uNNNN`|Một ký tự Unicode hex code `NNNN`, Ví dụ `\u00A9` -- là dấu bản quyền `©`.| +|`\u{NNNNNNNN}`|Một vài ký tự Unicode đặc biệt, chiếm 4 bytes. Nó cần được nằm trong cặp ngoặc nhọn.| -Examples with unicode: +Vài ví dụ với unicode: ```js run alert( "\u00A9" ); // © @@ -92,9 +89,9 @@ alert( "\u{20331}" ); // 佫, a rare chinese hieroglyph (long unicode) alert( "\u{1F60D}"); // 😍, a smiling face symbol (another long unicode) ``` -All special characters start with a backslash character `\`. It is also called an "escape character". +Một ký tự đặc biệt được bắt đầu bởi dấu `\`. Nó được gọi là ký tự thoát "escape character". -We would also use it if we want to insert a quote into the string. +Cũng sử dụng khi string có dấu nháy. For instance: @@ -102,19 +99,19 @@ For instance: alert( 'I*!*\'*/!*m the Walrus!' ); // *!*I'm*/!* the Walrus! ``` -As you can see, we have to prepend the inner quote by the backslash `\'`, because otherwise it would indicate the string end. +Ta phải sử dụng `\'`, vì nó cũng đại diện cho bắt đầu và kết thúc string. -Of course, that refers only to the quotes that are same as the enclosing ones. So, as a more elegant solution, we could switch to double quotes or backticks instead: +Tất nhiên nếu khác thì không cần sử dụng: ```js run alert( `I'm the Walrus!` ); // I'm the Walrus! ``` -Note that the backslash `\` serves for the correct reading of the string by JavaScript, then disappears. The in-memory string has no `\`. You can clearly see that in `alert` from the examples above. +Dấu `\` sẽ không hiển thị, nó chỉ dùng để thể hiện cho JS là biết là bắt đầu một ký tự đặc biệt. Trong bộ nhớ sẽ không có `\`. -But what if we need to show an actual backslash `\` within the string? +Khi cần in ra dấu `\`trong string? -That's possible, but we need to double it like `\\`: +Ta dùng 2 dấu `\\`: ```js run alert( `The backslash: \\` ); // The backslash: \ @@ -123,23 +120,23 @@ alert( `The backslash: \\` ); // The backslash: \ ## String length -The `length` property has the string length: +`length` property thể hiện độ dài của string: ```js run alert( `My\n`.length ); // 3 ``` -Note that `\n` is a single "special" character, so the length is indeed `3`. +Chú ý `\n` chỉ tính là một ký tự, nên ví dụ trên có độ dài là `3`. -```warn header="`length` is a property" -People with a background in some other languages sometimes mistype by calling `str.length()` instead of just `str.length`. That doesn't work. +```warn header="`length` là một property" +Đừng sử dụng nhầm `str.length()` thay vì `str.length`, như những ngôn ngữ khác. -Please note that `str.length` is a numeric property, not a function. There is no need to add brackets after it. +Chú ý `str.length` là một property, không phải là một hàm. Nên khi gọi không có cặp dấu ngoặc tròn. ``` -## Accessing characters +## Truy cập các phần tử của string -To get a character at position `pos`, use square brackets `[pos]` or call the method [str.charAt(pos)](mdn:js/String/charAt). The first character starts from the zero position: +Lấy ký tự ở vị trí `pos`, sử dụng ngoặc vuông `[pos]` hoặc dùng method [str.charAt(pos)](mdn:js/String/charAt). Ký tự đầu tiên có vị trí bằng `0`: ```js run let str = `Hello`; @@ -151,10 +148,8 @@ alert( str.charAt(0) ); // H // the last character alert( str[str.length - 1] ); // o ``` - -The square brackets are a modern way of getting a character, while `charAt` exists mostly for historical reasons. - -The only difference between them is that if no character is found, `[]` returns `undefined`, and `charAt` returns an empty string: +Dùng charAt là theo các bản JS cũ. bản ES6 nên dùng [] +Sự khác nhau giữa chúng là, `[pos]` trả về `undefined`, và `charAt(pos)` trả về `''` khi không có vị trí `pos`. ```js run let str = `Hello`; @@ -163,7 +158,7 @@ alert( str[1000] ); // undefined alert( str.charAt(1000) ); // '' (an empty string) ``` -We can also iterate over characters using `for..of`: +Duyệt qua string bằng `for..of`: ```js run for(let char of "Hello") { @@ -171,11 +166,11 @@ for(let char of "Hello") { } ``` -## Strings are immutable +## Strings là immutable -Strings can't be changed in JavaScript. It is impossible to change a character. +Strings là không thể thay đổi trong JavaScript. -Let's try it to show that it doesn't work: +Ví dụ: ```js run let str = 'Hi'; @@ -184,9 +179,7 @@ str[0] = 'h'; // error alert( str[0] ); // doesn't work ``` -The usual workaround is to create a whole new string and assign it to `str` instead of the old one. - -For instance: +Cho nên chỉ có thể gán lại, chứ không thể thay đổi: ```js run let str = 'Hi'; @@ -196,34 +189,33 @@ str = 'h' + str[1]; // replace the string alert( str ); // hi ``` -In the following sections we'll see more examples of this. -## Changing the case +## Viết hoa, thường -Methods [toLowerCase()](mdn:js/String/toLowerCase) and [toUpperCase()](mdn:js/String/toUpperCase) change the case: +Methods [toLowerCase()](mdn:js/String/toLowerCase) và [toUpperCase()](mdn:js/String/toUpperCase) thay đổi kiểu hoa, thường của string: ```js run alert( 'Interface'.toUpperCase() ); // INTERFACE alert( 'Interface'.toLowerCase() ); // interface ``` -Or, if we want a single character lowercased: +hoặc, chỉ thay đổi một ký tự: ```js alert( 'Interface'[0].toLowerCase() ); // 'i' ``` -## Searching for a substring +## tìm substring -There are multiple ways to look for a substring within a string. +Có nhiều cách để tìm một chuỗi con - substring trong một string cho trước. ### str.indexOf -The first method is [str.indexOf(substr, pos)](mdn:js/String/indexOf). +Đầu tiên là method [str.indexOf(substr, pos)](mdn:js/String/indexOf). -It looks for the `substr` in `str`, starting from the given position `pos`, and returns the position where the match was found or `-1` if nothing can be found. +Tìm `substr` trong `str`, bắt đầu từ vị trí `pos`, trả về vị trí chứa subtring hoặc `-1` nếu không tìm thấy. -For instance: +Ví dụ: ```js run let str = 'Widget with id'; @@ -234,9 +226,9 @@ alert( str.indexOf('widget') ); // -1, not found, the search is case-sensitive alert( str.indexOf("id") ); // 1, "id" is found at the position 1 (..idget with id) ``` -The optional second parameter allows us to search starting from the given position. +Tham số `pos` là optional, mặc định bằng `0`. -For instance, the first occurrence of `"id"` is at position `1`. To look for the next occurrence, let's start the search from position `2`: +Ví dụ, vị trí của `"id"` đầu tiên là `1`. tìm tiếp thì ta sử dụng với `pos` là `2`: ```js run let str = 'Widget with id'; @@ -245,8 +237,7 @@ alert( str.indexOf('id', 2) ) // 12 ``` -If we're interested in all occurrences, we can run `indexOf` in a loop. Every new call is made with the position after the previous match: - +Nếu muốn tìm hết, ta dùng `indexOf` trong vòng lặp. ```js run let str = 'As sly as a fox, as strong as an ox'; @@ -263,7 +254,7 @@ while (true) { } ``` -The same algorithm can be layed out shorter: +Cách ngắn hơn: ```js run let str = "As sly as a fox, as strong as an ox"; @@ -278,12 +269,12 @@ while ((pos = str.indexOf(target, pos + 1)) != -1) { ``` ```smart header="`str.lastIndexOf(pos)`" -There is also a similar method [str.lastIndexOf(pos)](mdn:js/String/lastIndexOf) that searches from the end of a string to its beginning. +Có một method tương tự [str.lastIndexOf(pos)](mdn:js/String/lastIndexOf), nó tìm từ cuối đến đầu string. -It would list the occurrences in the reverse order. +kết quả sẽ đảo ngược. ``` -There is a slight inconvenience with `indexOf` in the `if` test. We can't put it in the `if` like this: +Có một sự bất tiện nhỏ với `indexOf` trong `if`. Như thế này: ```js run let str = "Widget with id"; @@ -293,9 +284,9 @@ if (str.indexOf("Widget")) { } ``` -The `alert` in the example above doesn't show because `str.indexOf("Widget")` returns `0` (meaning that it found the match at the starting position). Right, but `if` considers `0` to be `false`. +Lệnh `alert` sẽ không được chạy vì `str.indexOf("Widget")` trả về `0`. Vì trong `if`, `0` là `false`. -So, we should actually check for `-1`, like this: +Nên ta kiểm tra với `-1`, như này: ```js run let str = "Widget with id"; @@ -307,12 +298,12 @@ if (str.indexOf("Widget") != -1) { } ``` -````smart header="The bitwise NOT trick" -One of the old tricks used here is the [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT) `~` operator. It converts the number to a 32-bit integer (removes the decimal part if exists) and then reverses all bits in its binary representation. +````smart header="Phép nhị phân NOT" +Sử dụng toán tử [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT) `~`. Nó convert sang số nguyên dạng 32 bit (removes the decimal part if exists) và đảo ngược giá trị các bit. -For 32-bit integers the call `~n` means exactly the same as `-(n+1)` (due to IEEE-754 format). +Với số nguyên 32-bit, gọi `~n` tương đương `-(n+1)` (do định dạng IEEE-754). -For instance: +Ví dụ: ```js run alert( ~2 ); // -3, the same as -(2+1) @@ -323,11 +314,9 @@ alert( ~-1 ); // 0, the same as -(-1+1) */!* ``` -As we can see, `~n` is zero only if `n == -1`. - -So, the test `if ( ~str.indexOf("...") )` is truthy that the result of `indexOf` is not `-1`. In other words, when there is a match. +Ta thấy, `~n` là bằng `0` khi và chỉ khi `n == -1`. -People use it to shorten `indexOf` checks: +Nên `if ( ~str.indexOf("...") )` là thứ ta cần cho ví dụ trên: ```js run let str = "Widget"; @@ -337,16 +326,16 @@ if (~str.indexOf("Widget")) { } ``` -It is usually not recommended to use language features in a non-obvious way, but this particular trick is widely used in old code, so we should understand it. +Tuy nhiên, việc viết như thế không được khuyến khích vì nó không rõ ràng Just remember: `if (~str.indexOf(...))` reads as "if found". ```` ### includes, startsWith, endsWith -The more modern method [str.includes(substr, pos)](mdn:js/String/includes) returns `true/false` depending on whether `str` contains `substr` within. +Những methods này là có trong bản JS mới. Method [str.includes(substr, pos)](mdn:js/String/includes) trả về `true/false` phụ thuộc vào ciệc liệu `str` có bao gồm `substr` hay không. -It's the right choice if we need to test for the match, but don't need its position: +Nếu không quan tâm đến `pos`: ```js run alert( "Widget with id".includes("Widget") ); // true @@ -354,28 +343,28 @@ alert( "Widget with id".includes("Widget") ); // true alert( "Hello".includes("Bye") ); // false ``` -The optional second argument of `str.includes` is the position to start searching from: +`pos` trong `str.includes` thể hiện vị trị bắt đầu tìm kiếm: ```js run alert( "Midget".includes("id") ); // true alert( "Midget".includes("id", 3) ); // false, from position 3 there is no "id" ``` -The methods [str.startsWith](mdn:js/String/startsWith) and [str.endsWith](mdn:js/String/endsWith) do exactly what they say: +Methods [str.startsWith](mdn:js/String/startsWith) và [str.endsWith](mdn:js/String/endsWith): ```js run alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid" alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get" ``` -## Getting a substring +## Lấy một substring -There are 3 methods in JavaScript to get a substring: `substring`, `substr` and `slice`. +Có 3 methods trong JavaScript để lấy substring: `substring`, `substr` và `slice`. `str.slice(start [, end])` -: Returns the part of the string from `start` to (but not including) `end`. +: Trả về một phần của str từ vị trí `start` đến (không bao gồm) `end`. - For instance: + Ví dụ: ```js run let str = "stringify"; @@ -383,14 +372,14 @@ There are 3 methods in JavaScript to get a substring: `substring`, `substr` and alert( str.slice(0,1) ); // 's', from 0 to 1, but not including 1, so only character at 0 ``` - If there is no second argument, then `slice` goes till the end of the string: + Nếu không có tham số `end` thì `slice` chạy đến cuối string: ```js run let str = "st*!*ringify*/!*"; alert( str.slice(2) ); // ringify, from the 2nd position till the end ``` - Negative values for `start/end` are also possible. They mean the position is counted from the string end: + Giá trị ấm cho `start/end` được sử dụng, nó có ý nghĩa sẽ bắt đầu từ cuối tring: ```js run let str = "strin*!*gif*/!*y"; @@ -401,11 +390,11 @@ There are 3 methods in JavaScript to get a substring: `substring`, `substr` and `str.substring(start [, end])` -: Returns the part of the string *between* `start` and `end`. +: trả về một phần của string *giữa* `start` và `end`. - This is almost the same as `slice`, but it allows `start` to be greater than `end`. + Tương tự `slice`, nhưng chấp nhận `start` lớn hơn `end`. - For instance: + Ví dụ: ```js run @@ -421,20 +410,20 @@ There are 3 methods in JavaScript to get a substring: `substring`, `substr` and ``` - Negative arguments are (unlike slice) not supported, they are treated as `0`. + Số âm không được chấp nhận (không giống slice) nó sẽ xem như là `0`. `str.substr(start [, length])` -: Returns the part of the string from `start`, with the given `length`. +: Trả về một phần của string, bắt đầu từ `start`, với `length` ký tự. - In contrast with the previous methods, this one allows us to specify the `length` instead of the ending position: + Ngược lại với các method trước, nó dùng `length` thay vì vị trí: ```js run let str = "st*!*ring*/!*ify"; alert( str.substr(2, 4) ); // ring, from the 2nd position get 4 characters ``` - The first argument may be negative, to count from the end: + `start` có thể là số âm, nghĩa là đếm từ cuối string: ```js run let str = "strin*!*gi*/!*fy"; @@ -450,38 +439,36 @@ Let's recap these methods to avoid any confusion: | `substr(start, length)` | from `start` get `length` characters | allows negative `start` | -```smart header="Which one to choose?" -All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere. - -The author finds himself using `slice` almost all the time. +```smart header="Nên dùng thằng nào?" +Dùng tất, nhưng thường thì sử dụng `slice` cho hầu hết các trường hợp. ``` -## Comparing strings +## So sánh strings -As we know from the chapter , strings are compared character-by-character in alphabetical order. +Đã học trong chương , strings được so sánh từng ký tự theo thứ tự trong bãng chữ cái. -Although, there are some oddities. +Mặc dù, có một số sự kỳ quặc. -1. A lowercase letter is always greater than the uppercase: +1. Chữ viết thường luôn lớn hơn chữ viết hoa: ```js run alert( 'a' > 'Z' ); // true ``` -2. Letters with diacritical marks are "out of order": +2. Chữ cái với dấu âm không sử dụng được: ```js run alert( 'Österreich' > 'Zealand' ); // true ``` - This may lead to strange results if we sort these country names. Usually people would expect `Zealand` to come after `Österreich` in the list. + Đây là một kết quả kỳ lạ khi sắp xếp tên các quốc gia. Thường thì người ta mong muốn `Zealand` nằm ở sau `Österreich` trong danh sách. -To understand what happens, let's review the internal representation of strings in JavaScript. +Để hiểu những gì xảy ra ta xem lại các biểu diễn string trong JavaScript. -All strings are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). That is: each character has a corresponding numeric code. There are special methods that allow to get the character for the code and back. +String được mã hóa theo định dạng [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Đó là: Mỗi ký tự sẽ có một mã số. Có một method đặc biệt để lấy được mã số này. `str.codePointAt(pos)` -: Returns the code for the character at position `pos`: +: Trả về mã ký tự ở vị trí `pos`: ```js run // different case letters have different codes @@ -490,20 +477,20 @@ All strings are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Th ``` `String.fromCodePoint(code)` -: Creates a character by its numeric `code` +: Tạo ra một ký tự với mã số là `code` ```js run alert( String.fromCodePoint(90) ); // Z ``` - We can also add unicode characters by their codes using `\u` followed by the hex code: + Ta cũng có thể sử dụng mã Unicode với `\u` và hex code: ```js run // 90 is 5a in hexadecimal system alert( '\u005a' ); // Z ``` -Now let's see the characters with codes `65..220` (the latin alphabet and a little bit extra) by making a string of them: +Giờ ta xem các ký tự với mã từ `65..220` : ```js run let str = ''; @@ -516,46 +503,46 @@ alert( str ); // ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ ``` -See? Capital characters go first, then a few special ones, then lowercase characters. +Thấy không, chữ hoa trước, rồi đến một vài ký tự đặc biệt, rồi đến chữ thường. -Now it becomes obvious why `a > Z`. +Giờ ta rõ ràng tại sao `a > Z`. -The characters are compared by their numeric code. The greater code means that the character is greater. The code for `a` (97) is greater than the code for `Z` (90). +Ký tự được so sánh bởi mã của nó. Mã lớn hơn thì lớn hơn, `a` (97) lớn hơn `Z` (90). -- All lowercase letters go after uppercase letters because their codes are greater. -- Some letters like `Ö` stand apart from the main alphabet. Here, it's code is greater than anything from `a` to `z`. +- Chữ thường lớn hơn chữ hoa. +- Các chữ cái `Ö` là một phần của bãng chữ cái, và nó có mã lớn hơn cả `a` đến `z`. -### Correct comparisons +### Sự so sánh đúng -The "right" algorithm to do string comparisons is more complex than it may seem, because alphabets are different for different languages. The same-looking letter may be located differently in different alphabets. +Thuật toán đúng để so sánh String là phức tạp hơn rất nhiều so với những gì chúng ta thấy. Vì bãng chữ cái sẽ khác nhau với các ngôn ngữ khác nhau. Một chữ cái có thể có mã code khác nhau tùy thuộc ngôn ngữ. -So, the browser needs to know the language to compare. +Nên, trình duyệt cần biết là ngôn ngữ nào được sử dụng để so sánh. -Luckily, all modern browsers (IE10- requires the additional library [Intl.JS](https://github.com/andyearnshaw/Intl.js/)) support the internationalization standard [ECMA 402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf). +May mắn thay, các trình duyệt ngày nay (IE10- cần [Intl.JS](https://github.com/andyearnshaw/Intl.js/)) hỗ trợ chuẩn quốc tế [ECMA 402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf). -It provides a special method to compare strings in different languages, following their rules. +Nó cung cấp một method đặc biệt để so sánh trong tất cả các ngôn ngữ. -The call [str.localeCompare(str2)](mdn:js/String/localeCompare): +Gọi là [str.localeCompare(str2)](mdn:js/String/localeCompare): -- Returns `1` if `str` is greater than `str2` according to the language rules. -- Returns `-1` if `str` is less than `str2`. -- Returns `0` if they are equal. +- Trả về `1` nếu `str` lớn hơn `str2` theo quy tắc ngôn ngữ đó. +- Trả về `-1` nếu `str` nhở hơn `str2`. +- Trả về `0` nếu bằng. -For instance: +Ví dụ: ```js run alert( 'Österreich'.localeCompare('Zealand') ); // -1 ``` -This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allow it to specify the language (by default taken from the environment) and setup additional rules like case sensivity or should `"a"` and `"á"` be treated as the same etc. +Method này có hai tham số được định nghĩa trong [the documentation](mdn:js/String/localeCompare), cho phép đặc tả ngôn ngữ (mặc định được lấy từ môi trường) và tạo ra các quy tắc, ví dụ `"a"` và `"á"` là như nhau... ## Internals, Unicode -```warn header="Advanced knowledge" -The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical of hieroglyphs characters or other rare symbols. +```warn header="Kiến thức nâng cao" +Phần này sẽ hữu ích nếu bạn sử dụng emoji, ký hiệu toán học, chữ tượng hình hoặc các ký tự đặc biệt. -You can skip the section if you don't plan to support them. +Có thể bõ qua nếu bạn không cần chúng. ``` ### Surrogate pairs @@ -656,21 +643,21 @@ In reality, this is not always the case. The reason being that the symbol `Ṩ If you want to learn more about normalization rules and variants -- they are described in the appendix of the Unicode standard: [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/), but for most practical purposes the information from this section is enough. -## Summary +## Tổng kết -- There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions. -- Strings in JavaScript are encoded using UTF-16. -- We can use special characters like `\n` and insert letters by their unicode using `\u...`. -- To get a character, use: `[]`. -- To get a substring, use: `slice` or `substring`. -- To lowercase/uppercase a string, use: `toLowerCase/toUpperCase`. -- To look for a substring, use: `indexOf`, or `includes/startsWith/endsWith` for simple checks. -- To compare strings according to the language, use: `localeCompare`, otherwise they are compared by character codes. +- Có 3 kiểu quotes. Backticks chấp nhận viết string nhiều hàng và nhúng biến, biểu thức. +- Strings trong JavaScript được mã hóa theo bãng mã UTF-16. +- Sử dụng các ký tự đặc biệt như `\n` và chèn chữ bởi mã Univode với `\u...`. +- Lấy ký tự sử dụng: `[]`. +- Lấy substring dùng: `slice` hoặc `substring`. +- Viết hoa/thường dùng: `toLowerCase/toUpperCase`. +- Tìm substring dùng: `indexOf`, or `includes/startsWith/endsWith` for simple checks. +- So sánh string dùng: `localeCompare`. -There are several other helpful methods in strings: +Một số methods hữu ích với strings: -- `str.trim()` -- removes ("trims") spaces from the beginning and end of the string. -- `str.repeat(n)` -- repeats the string `n` times. -- ...and more. See the [manual](mdn:js/String) for details. +- `str.trim()` -- bõ ("trims") các dấu space ở đầu và cuối string. +- `str.repeat(n)` -- repeats string `n` lần. +- ...Và nhiều hơn, xem tại [manual](mdn:js/String). -Strings also have methods for doing search/replace with regular expressions. But that topic deserves a separate chapter, so we'll return to that later. +Strings cũng có methods để search/replace với biểu thức chính quy - regular expressions. Nhưng ta sẽ học trong chương khác. From 82c43e851ef84aa1b87e7b0dad97f69e298a401e Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 9 Nov 2017 12:04:28 +0700 Subject: [PATCH 75/78] Update article.md --- 1-js/05-data-types/04-array/article.md | 218 ++++++++++++------------- 1 file changed, 108 insertions(+), 110 deletions(-) diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md index 781699f7d1..9fe85dfbc8 100644 --- a/1-js/05-data-types/04-array/article.md +++ b/1-js/05-data-types/04-array/article.md @@ -1,33 +1,33 @@ # Arrays -Objects allow to store keyed collections of values. That's fine. +Objects cho phép lưu trữ các bộ key-value. -But quite often we find that we need an *ordered collection*, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc. +Nhưng ta cần một * bộ có thứ tự - ordered collection*, với giá trị 1st, 2nd, 3rd ... Ví dụ ta cần lưu một bộ giá trị: users, goods, HTML elements ... -It is not convenient to use an object here, because it provides no methods to manage the order of elements. We can’t insert a new property “between” the existing ones. Objects are just not meant for such use. +Sẽ không thích hợp khi sử dụng object ở đây, Bởi vì nó không sắp xếp được các giá trị của nó. Ta không thể chèn vào một property mới “ở giữa” các property đã có. -There exists a special data structure named `Array`, to store ordered collections. +Có một cấu trúc dữ liệu được gọi là mãng `Array`, để lưu trữ các bộ có thứ tự. [cut] -## Declaration +## Khai báo -There are two syntaxes for creating an empty array: +Có hai cách tạo ra một Array rỗng: ```js let arr = new Array(); let arr = []; ``` -Almost all the time, the second syntax is used. We can supply initial elements in the brackets: +Cách thứ hai hay được sử dụng, ta có thể khởi tạo luôn các Array element: ```js let fruits = ["Apple", "Orange", "Plum"]; ``` -Array elements are numbered, starting with zero. +Array elements được đánh số thứ tự, bắt đầu từ 0. -We can get an element by its number in square brackets: +Ta truy xuất các element thông qua số thứ tự của nó trong dấu ngoặc vuông: ```js run let fruits = ["Apple", "Orange", "Plum"]; @@ -37,19 +37,19 @@ alert( fruits[1] ); // Orange alert( fruits[2] ); // Plum ``` -We can replace an element: +Gán lại giá trị cho element: ```js fruits[2] = 'Pear'; // now ["Apple", "Orange", "Pear"] ``` -...Or add a new one to the array: +...hoặc add thêm element cho array: ```js fruits[3] = 'Lemon'; // now ["Apple", "Orange", "Pear", "Lemon"] ``` -The total count of the elements in the array is its `length`: +Tổng số element trong array là độ dài `length` của array: ```js run let fruits = ["Apple", "Orange", "Plum"]; @@ -57,7 +57,7 @@ let fruits = ["Apple", "Orange", "Plum"]; alert( fruits.length ); // 3 ``` -We can also use `alert` to show the whole array. +Ta có thể `alert` toàn bộ array. ```js run let fruits = ["Apple", "Orange", "Plum"]; @@ -65,9 +65,9 @@ let fruits = ["Apple", "Orange", "Plum"]; alert( fruits ); // Apple,Orange,Plum ``` -An array can store elements of any type. +element có thể là bất cứ loại dữ liệu nào. -For instance: +Ví dụ: ```js run no-beautify // mix of values @@ -82,7 +82,7 @@ arr[3](); // hello ````smart header="Trailing comma" -An array, just like an object, may end with a comma: +Một array, cũng như object, nên kết thúc bởi dấu phẩy: ```js let fruits = [ "Apple", @@ -91,46 +91,44 @@ let fruits = [ ]; ``` -The "trailing comma" style makes it easier to insert/remove items, because all lines become alike. +"trailing comma" dễ dàng hơn cho việc insert/remove items, bởi vì tất cả các dòng đều như nhau. ```` ## Methods pop/push, shift/unshift -A [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) is one of most common uses of an array. In computer science, this means an ordered collection of elements which supports two operations: +Một hàng đợi [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) là một trong những cách dùng array phổ biến. Trong khoa học máy tính, hàng đợi là một bộ thứ tự hỗ trợ các hành động: -- `push` appends an element to the end. -- `shift` get an element from the beginning, advancing the queue, so that the 2nd element becomes the 1st. +- `push` nối một element vào cuối. +- `shift` lấy element đầu tiên, và loại nó ra khỏi queue, cho nên 2nd element sẽ trở thành 1st. ![](queue.png) -Arrays support both operations. +Arrays hỗ trợ cả hai hành động trên. -In practice we meet it very often. For example, a queue of messages that need to be shown on-screen. +Trong thực tế ta gặp các queue rất nhiều, ví dụ một message list để in ra màn hình. -There's another use case for arrays -- the data structure named [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)). +Có một cách sử dụng khác với arrays -- một cấu trúc dữ liệu có tên là ngăn xếp [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)). -It supports two operations: +Nó hỗ trợ hai hành động: -- `push` adds an element to the end. -- `pop` takes an element to the end. +- `push` thêm element vào cuối stack. +- `pop` bõ element cuối stack. -So new elements are added or taken always from the "end". - -A stack is usually illustrated as a pack of cards: new cards are added to the top or taken from the top: +element được thêm hay loại bõ đều ở cuối stack. ![](stack.png) -For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out). +Với stack, element được đưa vào cuối cùng sẽ được lấy ra đầu tiên, nguyên tắc này gọi là LIFO (Last-In-First-Out). Với queue, ta có FIFO (First-In-First-Out). -Arrays in JavaScript can work both as a queue and as a stack. They allow to add/remove elements both to/from the beginning or the end. +Arrays trong JavaScript có thể hoạt động như queue và stack. Chúng cho phép add/remove elements theo phía bắt đầu lẫn cuối array. -In computer science the data structure that allows it is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue). +Trong khoa học máy tính, những cấu trúc dữ liệu như thế được gọi là hàng đợi hai đầu [deque](https://en.wikipedia.org/wiki/Double-ended_queue). -**Methods that work with the end of the array:** +**Methods hoạt động theo element cuối array:** `pop` -: Extracts the last element of the array and returns it: +: Lấy element cuối cùng ra khỏi array, trả về chính element đó: ```js run let fruits = ["Apple", "Orange", "Pear"]; @@ -141,7 +139,7 @@ In computer science the data structure that allows it is called [deque](https:// ``` `push` -: Append the element to the end of the array: +: thêm element vào cuối array, trả về length của array: ```js run let fruits = ["Apple", "Orange"]; @@ -156,7 +154,7 @@ In computer science the data structure that allows it is called [deque](https:// **Methods that work with the beginning of the array:** `shift` -: Extracts the first element of the array and returns it: +: Lấy element đầu tiên ra khỏi array, trả về element đó: ```js let fruits = ["Apple", "Orange", "Pear"]; @@ -167,7 +165,7 @@ In computer science the data structure that allows it is called [deque](https:// ``` `unshift` -: Add the element to the beginning of the array: +: thêm element vào đầu array, trả về length của array: ```js let fruits = ["Orange", "Pear"]; @@ -177,7 +175,7 @@ In computer science the data structure that allows it is called [deque](https:// alert( fruits ); // Apple, Orange, Pear ``` -Methods `push` and `unshift` can add multiple elements at once: +Methods `push` và `unshift` có thể add nhiều element trong một lần gọi: ```js run let fruits = ["Apple"]; @@ -191,13 +189,13 @@ alert( fruits ); ## Internals -An array is a special kind of object. The square brackets used to access a property `arr[0]` actually come from the object syntax. Numbers are used as keys. +Array là một kiểu object đặc biệt. Cặp ngoặc vuông để truy xuất property `arr[0]` thực sự là đến từ cú pháp của object. Numbers được sử dụng làm keys. -They extend objects providing special methods to work with ordered collections of data and also the `length` property. But at the core it's still an object. +Object này được mở rộng để cung cấp thêm các method, cũng như `length` property. Nhưng về cơ bản thì array vẫn là một object. -Remember, there are only 7 basic types in JavaScript. Array is an object and thus behaves like an object. +Nên nhớ chỉ có 7 kiểu dữ liệu trong JavaScript. Array chỉ là object, và do đó các hành vi của nó tương tự object. -For instance, it is copied by reference: +Ví dụ, nó cũng được copy bởi tham chiếu: ```js run let fruits = ["Banana"] @@ -211,11 +209,11 @@ arr.push("Pear"); // modify the array by reference alert( fruits ); // Banana, Pear - 2 items now ``` -...But what makes arrays really special is their internal representation. The engine tries to store its elements in the contiguous memory area, one after another, just as depicted on the illustrations in this chapter, and there are other optimizations as well, to make arrays work really fast. +...nhưng cái gì làm cho array trở nên đặc biệt? JavaScript Engine sẽ lưu trữ chúng trong một vùng nhớ liên tục, element này nối tiếp element khác, như cách ta tìm hiểu về JS engine tối ưu ở các chương trước, sử dụng array cũng giúp cho chương trình chạy nhanh hơn là object. -But they all break if we quit working with an array as with an "ordered collection" and start working with it as if it were a regular object. +Nhưng sẽ là không ổn nếu ta sử dụng array theo cách của object. -For instance, technically we can do this: +Ví dụ, về kỹ thuật code như bên dưới vẫn chạy được: ```js let fruits = []; // make an array @@ -225,47 +223,47 @@ fruits[99999] = 5; // assign a property with the index far greater than its leng fruits.age = 25; // create a property with an arbitrary name ``` -That's possible, because arrays are objects at their base. We can add any properties to them. +Điều này có thể, vì array vẫn là object, nên nó cũng có các property. -But the engine will see that we're working with the array as with a regular object. Array-specific optimizations are not suited for such cases and will be turned off, their benefits disappear. +Nhưng JS Engine sẽ coi array như một object chính quy. Và những ưu điểm của aray trong việc tối ưu cho chương trình sẽ bị bõ qua. -The ways to misuse an array: +Những cách lạm dụng array mà ta không nên sử dụng: -- Add a non-numeric property like `arr.test = 5`. -- Make holes, like: add `arr[0]` and then `arr[1000]` (and nothing between them). -- Fill the array in the reverse order, like `arr[1000]`, `arr[999]` and so on. +- Thêm một non-numeric property như `arr.test = 5`. +- Tạo các lỗ trống: add `arr[0]` và sau đó `arr[1000]` (không có gì ở giữa chúng). +- Lấp đầy array theo thứ tự ngược `arr[1000]`, `arr[999]` ... -Please think of arrays as special structures to work with the *ordered data*. They provide special methods for that. Arrays are carefully tuned inside JavaScript engines to work with contiguous ordered data, please use them this way. And if you need arbitrary keys, chances are high that you actually require a regular object `{}`. +Hãy suy nghĩ array như với một bộ *dữ liệu có thứ tự*. Chúng cung cấp các method đặc biệt. Arrays được điều chỉnh trong JavaScript engines để làm việc với dữ liệu một cách liên tục, hãy sử dụng chúng với cách này. Nếu muốn sử dụng một key trừu tượng, hãy sử dụng nó với `{}`. ## Performance -Methods `push/pop` run fast, while `shift/unshift` are slow. +Methods `push/pop` chạy rất nhanh, nhưng `shift/unshift` thì chậm. ![](array-speed.png) -Why is it faster to work with the end of an array than with its beginning? Let's see what happens during the execution: +Tại sao nhanh khi xử lý cuối array và chậm nếu method xử lý đầu aray? Ta sẽ xem xét điều gì xảy ra khi thực hiện các methods này: ```js fruits.shift(); // take 1 element from the start ``` -It's not enough to take and remove the element with the number `0`. Other elements need to be renumbered as well. +Sẽ không đủ nếu chỉ bõ element ở vị trí `0`. Các element khác cần được đánh số thứ tự lại. -The `shift` operation must do 3 things: +Method `shift` sẽ làm 3 bước: -1. Remove the element with the index `0`. -2. Move all elements to the left, renumber them from the index `1` to `0`, from `2` to `1` and so on. -3. Update the `length` property. +1. Xóa element có index `0`. +2. Di chuyển các element khác sang trái, `1` đến `0`, từ `2` đến `1` ... +3. Cập nhật lại `length` property. ![](array-shift.png) -**The more elements in the array, the more time to move them, more in-memory operations.** +**Càng có nhiều element trong array, càng di chuyển nhiều , chương trình sẽ càng chậm.** -The similar thing happens with `unshift`: to add an element to the beginning of the array, we need first to move existing elements to the right, increasing their indexes. +Tương tự với `unshift`: để thêm element vào đầu array, các element sẽ phải di chuyển sang phải. -And what's with `push/pop`? They do not need to move anything. To extract an element from the end, the `pop` method cleans the index and shortens `length`. +Và với `push/pop`? Các element sẽ không phải di chuyển, mà chỉ thêm/xóa element cuối cùng, và cập nhật lại `length`. -The actions for the `pop` operation: +Hoạt động của `pop`: ```js fruits.pop(); // take 1 element from the end @@ -273,13 +271,13 @@ fruits.pop(); // take 1 element from the end ![](array-pop.png) -**The `pop` method does not need to move anything, because other elements keep their indexes. That's why it's blazingly fast.** +**Method `pop` không cần di chuyển element, bởi vì chúng vẫn giữ nguyên index. Vì vậy nó chạy rất nhanh.** -The similar thing with the `push` method. +Tương tự với method `push`. ## Loops -One of the oldest ways to cycle array items is the `for` loop over indexes: +Một cách cổ xưa hay dùng là `for` với các indexes của array: ```js run let arr = ["Apple", "Orange", "Pear"]; @@ -291,7 +289,7 @@ for (let i = 0; i < arr.length; i++) { } ``` -But for arrays there is another form of loop, `for..of`: +Nhưng ta có một cách khác hay hơn là, `for..of`: ```js run let fruits = ["Apple", "Orange", "Plum"]; @@ -302,9 +300,9 @@ for(let fruit of fruits) { } ``` -The `for..of` doesn't give access to the number of the current element, just its value, but in most cases that's enough. And it's shorter. +Lệnh `for..of` không cho ra index của element, chỉ cho giá trị của element. Và hầu hết các trường hợp như thế là quá đủ. -Technically, because arrays are objects, it is also possible to use `for..in`: +Về mặt kỹ thuậ, vì array là một object nên có thể sử dụng `for..in`: ```js run let arr = ["Apple", "Orange", "Pear"]; @@ -316,22 +314,22 @@ for (let key in arr) { } ``` -But that's actually a bad idea. There are potential problems with it: +Nhưng đó thực sự là một ý tưởng tồi. Có những vấn đề tiềm ẩn: -1. The loop `for..in` iterates over *all properties*, not only the numeric ones. +1. Vòng lặp `for..in` lặp qua *tất cả properties*, không chỉ là các numeric property. - There are so-called "array-like" objects in the browser and in other environments, that *look like arrays*. That is, they have `length` and indexes properties, but they may also have other non-numeric properties and methods, which we usually don't need. The `for..in` loop will list them though. So if we need to work with array-like objects, then these "extra" properties can become a problem. + Và trong array sẽ có nhiều property khác như length, các method.... -2. The `for..in` loop is optimized for generic objects, not arrays, and thus is 10-100 times slower. Of course, it's still very fast. The speedup may matter only in bottlenecks or just irrelevant. But still we should be aware of the difference. +2. Vòng lặp `for..in` được tối ưu cho các object tiêu chuẩn, không phải arrays, và do đó sẽ bị chậm 10-100 lần. Tất nhiên vẫn rất nhanh, nhưng nếu như ta dùng một triệu lần như thế thì chương trình sẽ chậm đi quá nhiều đúng không. -Generally, we shouldn't use `for..in` for arrays. +Nói tóm lại, chỉ nên dùng `for..in` đối với arrays. -## A word about "length" +## Nói về "length" -The `length` property automatically updates when we modify the array. To be precise, it is actually not the count of values in the array, but the greatest numeric index plus one. +`length` property tự động cập nhật khi ta chỉnh sửa array. Nói tóm lại, giá trị của nó bằng với index lớn nhất, chứ không phải là đếm số index. -For instance, a single element with a large index gives a big length: +Ví dụ: ```js run let fruits = []; @@ -340,11 +338,11 @@ fruits[123] = "Apple"; alert( fruits.length ); // 124 ``` -Note that we usually don't use arrays like that. +Chú ý là không sử dụng như ví dụ trên, lấy ra để hiểu vấn đề thôi. -Another interesting thing about the `length` property is that it's writable. +Một sự thú vị khác với `length` property là có thể ghi đè. -If we increase it manually, nothing interesting happens. But if we decrease it, the array is truncated. The process is irreversible, here's the example: +Nếu ta tăng giá trị của length sẽ chẳng có gì xảy ra, nhưng nếu ta giảm giá trị của length, array sẽ bị cắt đi một phần: ```js run let arr = [1, 2, 3, 4, 5]; @@ -356,22 +354,22 @@ arr.length = 5; // return length back alert( arr[3] ); // undefined: the values do not return ``` -So, the simplest way to clear the array is: `arr.length=0`. +Nên cách đơn giản nhất để xóa một array là: `arr.length=0`. ## new Array() [#new-array] -There is one more syntax to create an array: +Có một cú pháp khác để tạo ra một array: ```js let arr = *!*new Array*/!*("Apple", "Pear", "etc"); ``` -It's rarely used, because square brackets `[]` are shorter. Also there's a tricky feature with it. +Nó ít được sử dụng, vì dùng`[]` sẽ ngắn gọn hơn. -If `new Array` is called with a single argument which is a number, then it creates an array *without items, but with the given length*. +Nếu `new Array` được gọi với một tham số là số nguyên *sẽ không có items, nhưng độ dài của aray chính là số nguyên đó*. -Let's see how one can shoot himself in the foot: +Xem ví dụ: ```js run let arr = new Array(2); // will it create an array of [2] ? @@ -381,13 +379,13 @@ alert( arr[0] ); // undefined! no elements. alert( arr.length ); // length 2 ``` -In the code above, `new Array(number)` has all elements `undefined`. +Trong code trên, `new Array(number)` có các element đều là `undefined`. -To evade such surprises, we usually use square brackets, unless we really know what we're doing. +Để tránh những điều trên, nên dùng cặp ngoặc vuông để tạo ra array. -## Multidimentional arrays +## Mãng nhiều chiều -Arrays can have items that are also arrays. We can use it for multidimentional arrays, to store matrices: +Arrays có thể có các item là arrays. Ta dùng nó để biễu diễn mãng nhiều chiều, như ma trận: ```js run let matrix = [ @@ -401,9 +399,9 @@ alert( matrix[1][1] ); // the central element ## toString -Arrays have their own implementation of `toString` method that returns a comma-separated list of elements. +Arrays có method `toString` riêng của nó, trả về các elements được phân tách bởi dấu phẩy. -For instance: +ví dụ: ```js run @@ -413,7 +411,7 @@ alert( arr ); // 1,2,3 alert( String(arr) === '1,2,3' ); // true ``` -Also, let's try this: +Thử: ```js run alert( [] + 1 ); // "1" @@ -421,9 +419,9 @@ alert( [1] + 1 ); // "11" alert( [1,2] + 1 ); // "1,21" ``` -Arrays do not have `Symbol.toPrimitive`, neither a viable `valueOf`, they implement only `toString` conversion, so here `[]` becomes an empty string, `[1]` becomes `"1"` and `[1,2]` becomes `"1,2"`. +Arrays không có `Symbol.toPrimitive`, và `valueOf`, Chúng chỉ có `toString` conversion, nên ở đây `[]` trở thành một chuỗi rỗng '', và `[1]` thành `"1"` và `[1,2]` thành `"1,2"`. -When the binary plus `"+"` operator adds something to a string, it converts it to a string as well, so the next step looks like this: +Khi dùng toán tử `"+"`, nếu có một toán hạng là string thì sẽ convert thành string: ```js run alert( "" + 1 ); // "1" @@ -431,11 +429,11 @@ alert( "1" + 1 ); // "11" alert( "1,2" + 1 ); // "1,21" ``` -## Summary +## Tổng kết -Array is a special kind of objects, suited to store and manage ordered data items. +Array là một objects đặc biệt, dùng lưu trữ dữ liệu có thứ tự. -- The declaration: +- Khai báo: ```js // square brackets (usual) @@ -445,22 +443,22 @@ Array is a special kind of objects, suited to store and manage ordered data item let arr = new Array(item1, item2...); ``` - The call to `new Array(number)` creates an array with the given length, but without elements. + Gọi `new Array(number)` tạo ra một array với length = number, nhưng không có elements. -- The `length` property is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods. -- If we shorten `length` manually, the array is truncated. +- `length` property là độ dài của arrat. Nó bằng index lớn nhất, và tự cập nhật khi array thay đổi. +- Nếu giảm giá trị `length`, array sẽ bị cắt bỏ một phần. -We can use an array as a deque with the following operations: +Ta sử dụng array như một deque: -- `push(...items)` adds `items` to the end. -- `pop()` removes the element from the end and returns it. -- `shift()` removes the element from the beginning and returns it. -- `unshift(...items)` adds items to the beginning. +- `push(...items)` thêm `items` vào cuối. +- `pop()` xóa item ở cuối và trả về item đó. +- `shift()` xóa item ở đầu và trả về item đó. +- `unshift(...items)` thêm item ở đầu. -To loop over the elements of the array: - - `for(let i=0; i. +Ta sẽ học thêm nhiều method của array ở chương . From 79a238b8b33416b18e7ab9b960bbf2b77a412817 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 9 Nov 2017 20:43:11 +0700 Subject: [PATCH 76/78] Update article.md --- .../05-data-types/05-array-methods/article.md | 148 +++++++++--------- 1 file changed, 72 insertions(+), 76 deletions(-) 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 d61a4a9780..dbcb0eb641 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -1,25 +1,25 @@ # Array methods -Arrays provide a lot of methods. To make things easier, in this chapter they are split into groups. +Arrays cung cấp nhiều methods giúp ta làm việc dễ hơn, trong chương này ta sẽ phân nhóm chúng. [cut] ## Add/remove items -We already know methods that add and remove items from the beginning or the end: +Ta đã biết các methods làm việc với đầu và cuối Array: - `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. -Here are few others. +Đây là một số methods khác. ### splice -How to delete an element from the array? +Làm sao để xóa một element từ array? -The arrays are objects, so we can try to use `delete`: +Array là một objects, nên ta có thể dùng `delete`: ```js run let arr = ["I", "go", "home"]; @@ -32,25 +32,21 @@ alert( arr[1] ); // undefined alert( arr.length ); // 3 ``` -The element was removed, but the array still has 3 elements, we can see that `arr.length == 3`. +Element bị xóa nhưng array vẫn có 3 elements, ta có thể thấy `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. +Đó là tự nhiên, bởi vì `delete obj.key` xóa value theo `key`. Nhưng với array ta muốn xóa element một cách thực sự. -So, special methods should be used. +Method [arr.splice(str)](mdn:js/Array/splice) cho phép ta add/remove/insert các element vào array. -The [arr.splice(str)](mdn:js/Array/splice) method is a swiss army knife for arrays. It can do everything: add, remove and insert elements. - -The syntax is: +Cú pháp: ```js arr.splice(index[, deleteCount, elem1, ..., elemN]) ``` -It starts from the position `index`: removes `deleteCount` elements and then inserts `elem1, ..., elemN` at their place. Returns the array of removed elements. - -This method is easy to grasp by examples. +Bắt đầu tự vị trí `index`: removes `deleteCount` elements và sau đó inserts `elem1, ..., elemN` vào đó. Trả về một array bị remove. -Let's start with the deletion: +Xem các ví dụ: ```js run let arr = ["I", "study", "JavaScript"]; @@ -62,9 +58,9 @@ arr.splice(1, 1); // from index 1 remove 1 element alert( arr ); // ["I", "JavaScript"] ``` -Easy, right? Starting from the index `1` it removed `1` element. +Dễ phải ko, bắt đầu từ vị trí index `1` xóa đi `1` element. -In the next example we remove 3 elements and replace them by the other two: +Ví dụ tiếp: ```js run let arr = [*!*"I", "study", "JavaScript",*/!* "right", "now"]; @@ -75,7 +71,7 @@ arr.splice(0, 3, "Let's", "dance") alert( arr ) // now [*!*"Let's", "dance"*/!*, "right", "now"] ``` -Here we can see that `splice` returns the array of removed elements: +Ở đây ta thấy `splice` trả về một array gồm các element bị xóa: ```js run let arr = [*!*"I", "study",*/!* "JavaScript", "right", "now"]; @@ -86,7 +82,7 @@ let removed = arr.splice(0, 2); alert( removed ); // "I", "study" <-- array of removed elements ``` -The `splice` method is also able to insert the elements without any removals. For that we need to set `deleteCount` to `0`: +`splice` method có thể dùng để insert element. Ta set `deleteCount` bằng `0`: ```js run let arr = ["I", "study", "JavaScript"]; @@ -99,8 +95,8 @@ arr.splice(2, 0, "complex", "language"); alert( arr ); // "I", "study", "complex", "language", "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="Index âm được chấp nhận" +Đây là một array methods khác, index âm được chấp nhận. Chúng xác định vị trí bắt đầu từ cuối array: ```js run let arr = [1, 2, 5] @@ -116,19 +112,19 @@ alert( arr ); // 1,2,3,4,5 ### slice -The method [arr.slice](mdn:js/Array/slice) is much simpler than similar-looking `arr.splice`. +Method [arr.slice](mdn:js/Array/slice) đơn giản hơn `arr.splice`. -The syntax is: +Cú pháp: ```js arr.slice(start, end) ``` -It returns a new array where it copies all items start index `"start"` to `"end"` (not including `"end"`). Both `start` and `end` can be negative, in that case position from array end is assumed. +Trả về một array chứa các element từ index `"start"` đến `"end"` (không bao gồm `"end"`). Cả `start` và `end` có thể âm, trường hợp này sẽ tính từ cuối array. -It works like `str.slice`, but makes subarrays instead of substrings. +Nó giống `str.slice`, nhưng trả về subarrays thay vì substrings. -For instance: +Ví dụ: ```js run let str = "test"; @@ -143,21 +139,21 @@ alert( arr.slice(-2) ); // s,t ### concat -The method [arr.concat](mdn:js/Array/concat) joins the array with other arrays and/or items. +Method [arr.concat](mdn:js/Array/concat) kết hợp các array với nhau thành một. -The syntax is: +Cú pháp: ```js arr.concat(arg1, arg2...) ``` -It accepts any number of arguments -- either arrays or values. +Có thể chứa nhiều tham số arg - với bất kỳ giá trị nào. -The result is a new array containing items from `arr`, then `arg1`, `arg2` etc. +Kết quả là một array mới bao gồm `arr`, tiếp theo là `arg1`, `arg2` ... -If an argument is an array or has `Symbol.isConcatSpreadable` property, then all its elements are copied. Otherwise the argument itself is copied. +Nếu `arg` là một array hoặc có `Symbol.isConcatSpreadable` property, thì tất cả element của nó sẽ được copy. Ngược lại sẽ copy chính `arg` đó. -For instance: +Ví dụ: ```js run let arr = [1, 2]; @@ -172,7 +168,7 @@ alert( arr.concat([3, 4], [5, 6])); // 1,2,3,4,5,6 alert( arr.concat([3, 4], 5, 6)); // 1,2,3,4,5,6 ``` -Normally, it only copies elements from arrays ("spreads" them), other objects even if they look like arrays and added as a whole: +Thông thường chỉ copy array, các object khác cho dù giống aray cũng được copy nguyên object thành một element: ```js run let arr = [1, 2]; @@ -186,7 +182,7 @@ alert( arr.concat(arrayLike) ); // 1,2,[object Object] //[1, 2, arrayLike] ``` -...But if an array-like object has `Symbol.isConcatSpreadable` property, then its elements are added instead: +...nhưng nếu array-like object có `Symbol.isConcatSpreadable` property, thì các element của nó sẽ được copy: ```js run let arr = [1, 2]; @@ -203,19 +199,19 @@ let arrayLike = { alert( arr.concat(arrayLike) ); // 1,2,something,else ``` -## Searching in array +## Tìm kiếm trong array -These are methods to search for something in an array. +Dưới là các method tìm kiếm trong 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: +Methods [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) và [arr.includes](mdn:js/Array/includes) có cú pháp và bản chất và cách hoạt động tương tự nhau: -- `arr.indexOf(item, from)` looks for `item` starting from index `from`, and returns the index where it was found, otheriwse `-1`. -- `arr.lastIndexOf(item, from)` -- same, but looks 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 `item` từ vị trí index `from`, trả về vị trí được tìm thấy, ngược lại trả về `-1`. +- `arr.lastIndexOf(item, from)` -- tương tự, nhưng tìm từ phải qua trái. +- `arr.includes(item, from)` -- tìm `item` từ vị trí `from`, trả về `true` nếu tìm thấy. -For instance: +Ví dụ: ```js run let arr = [1, 0, false]; @@ -227,33 +223,33 @@ 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. +Những methods này sử dụng phép so sánh `===`. Cho nên nếu ta tìm kiếm `false`, nó sẽ tìm chính xác `false` chứ không phải zero. -If we want to check for inclusion, and don't want to know the exact index, then `arr.includes` is preferred. +Nếu chỉ muốn tìm có hay không, và không cần biết index, nên dùng `arr.includes(item)` -### find and findIndex +### find và findIndex -Imagine we have an array of objects. How do we find an object with the specific condition? +Tưởng tượng ta có một array chứa các objects. Làm sao tìm được object thỏa mãn một điều kiện nào đó? -Here the [arr.find](mdn:js/Array/find) method comes in handy. +Ta sử dụng method [arr.find](mdn:js/Array/find). -The syntax is: +Cú pháp: ```js let result = arr.find(function(item, index, array) { // should return true if the item is what we are looking for }); ``` -The function is called repetitively for each element of the array: +function sẽ được gọi lặp đi lặp lại cho mỗi element của array: -- `item` is the element. -- `index` is its index. -- `array` is the array itself. +- `item` là element. +- `index` là index của element trê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`, việc tìm kiếm kết thúc, `item` tìm thấy được trả về. Nếu không tìm thấy thì trả về `undefined`. -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ụ, tìm object trong array có `id == 1`: ```js run let users = [ @@ -267,19 +263,19 @@ 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ế, một array chứa các object rất hay được sử dụng, vì lẽ đó method `find` là rất hữu ích. -Note that in the example we provide to `find` a single-argument function `item => item.id == 1`. Other parameters of `find` are rarely used. +Chú ý rằng với ví dụ trên, `find` chỉ có một tham số `item => item.id == 1`. Các tham số khác của hàm `find` 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. +Method [arr.findIndex](mdn:js/Array/findIndex) là tương tự nhưng nó trả về vị trí index thay vì trả về element. ### filter -The `find` method looks for a single (first) element that makes the function return `true`. +`find` method tìm một item đơn (đầu tiên) làm cho function trả về `true`. -If there may be many, we can use [arr.filter(fn)](mdn:js/Array/filter). +Nếu như tìm nhiều element thỏa mãn điều kiện, ta dùng [arr.filter(fn)](mdn:js/Array/filter). -The syntax is roughly the same as `find`, but it returns an array of matching elements: +Cú pháp tương tự `find`, nhưng nó trả về một array chứa các item thỏa mãn điều điệu: ```js let results = arr.filter(function(item, index, array) { @@ -302,16 +298,16 @@ let someUsers = users.filter(item => item.id < 3); alert(someUsers.length); // 2 ``` -## Transform an array +## Biến đổi một array -This section is about the methods transforming or reordering the array. +Phần này ta tìm hiểu các methods biến đổi hoặc 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. +[arr.map](mdn:js/Array/map) method thường rất hay được sử dụng. -The syntax is: +Cú pháp: ```js let result = arr.map(function(item, index, array) { @@ -319,9 +315,9 @@ let result = arr.map(function(item, index, array) { }) ``` -It calls the function for each element of the array and returns the array of results. +Gọi hàm với mỗi element của array, trả về một array chứa kết quả. -For instance, here we transform each element into its length: +Ví dụ: ```js run let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length) @@ -330,9 +326,9 @@ alert(lengths); // 5,7,6 ### sort(fn) -The method [arr.sort](mdn:js/Array/sort) sorts the array *in place*. +Method [arr.sort](mdn:js/Array/sort) sắp xếp lại array *trong vị trí*. -For instance: +Ví dụ: ```js run let arr = [ 1, 2, 15 ]; @@ -343,17 +339,17 @@ arr.sort(); alert( arr ); // *!*1, 15, 2*/!* ``` -Did you notice anything strange in the outcome? +Có thấy kỳ lạ không? -The order became `1, 15, 2`. Incorrect. But why? +Sắp xếp thành `1, 15, 2`. Sai, nhưng tại sao? -**The items are sorted as strings by default.** +**Item được sắp xếp theo String ở mặc định.** -Literally, all elements are converted to strings and then compared. So, the lexicographic ordering is applied and indeed `"2" > "15"`. +Theo nghĩa đen, tất cả item sẽ được convert sang string, sau đó so sánh. Vì vậy `"2" > "15"`. -To use our own sorting order, we need to supply a function of two arguments as the argument of `arr.sort()`. +Để sắp xếp như mong muốn, ta cần tạo ra một hàm với hai tham số, và truyền hàm đó cho `arr.sort()`. -The function should work like this: +Như thế này: ```js function compare(a, b) { if (a > b) return 1; @@ -362,7 +358,7 @@ function compare(a, b) { } ``` -For instance: +Ví dụ: ```js run function compareNumeric(a, b) { @@ -380,7 +376,7 @@ arr.sort(compareNumeric); alert(arr); // *!*1, 2, 15*/!* ``` -Now it works as intended. +Bây giờ nó hoạt động như mong muốn. Let's step aside and think what's happening. The `arr` can be array of anything, right? It may contain numbers or strings or html elements or whatever. We have a set of *something*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order. From bdf08823d8264fc6f2d2819567bce0755ac5acf8 Mon Sep 17 00:00:00 2001 From: Son Tran Date: Thu, 9 Nov 2017 23:12:24 +0700 Subject: [PATCH 77/78] Update article.md --- .../05-data-types/05-array-methods/article.md | 88 +++++++++---------- 1 file changed, 43 insertions(+), 45 deletions(-) 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 dbcb0eb641..576a57b0d3 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -380,9 +380,9 @@ Bây giờ nó hoạt động như mong muốn. Let's step aside and think what's happening. The `arr` can be array of anything, right? It may contain numbers or strings or html elements or whatever. We have a set of *something*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order. -The `arr.sort(fn)` method has a built-in implementation of sorting algorithm. We don't need to care how it exactly works (an optimized [quicksort](https://en.wikipedia.org/wiki/Quicksort) 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. +Method `arr.sort(fn)` tự thực hiện các thuật toán phân loại. Ta không cần quan tâm nó hoạt động bằng cách nào (Một cách sắp xếp tối ưu [quicksort](https://en.wikipedia.org/wiki/Quicksort) hầu hết thời gian). Nó sẽ lướt qua array, thực hiện các phép so sánh theo hàm `fn` mà ta cung cấp để thực hiện các phép 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 những element nào được so sánh -- không có gì xuất hiện khi alert chúng: ```js run [1, -2, 15, 2, 0, 8].sort(function(a, b) { @@ -390,13 +390,13 @@ By the way, if we ever want to know which elements are compared -- nothing preve }); ``` -The algorithm may compare an element multiple times 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ử nhiều lần trong tiến trình (process), nhưng nó sẽ cố gắng thực hiện càng ít phép so sánh nhất có thể. -````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 cứ số nào" +Thật sự, hàm so sánh chỉ cần trả về số dương để ngụ rằng "lớn hơn" số âm "nhỏ hơn". -That allows to write shorter functions: +Có thể viết ngắn hơn như sau: ```js run let arr = [ 1, 2, 15 ]; @@ -407,21 +407,21 @@ alert(arr); // *!*1, 2, 15*/!* ``` ```` -````smart header="Arrow functions for the best" -Remember [arrow functions](info:function-expression#arrow-functions)? We can use them here for neater sorting: +````smart header="Arrow functions là tốt nhất" +Có nhớ [arrow functions](info:function-expression#arrow-functions)? Ta có thể sử dụng để làm hàm so sánh: ```js arr.sort( (a, b) => a - b ); ``` -This works exactly the same as the other, longer, version above. +Nó hoạt động như các cách khác. ```` -### reverse +### Đảo ngược - reverse -The method [arr.reverse](mdn:js/Array/reverse) reverses the order of elements in `arr`. +Method [arr.reverse](mdn:js/Array/reverse) đảo ngược thứ tự trong mảng `arr`. -For instance: +Ví dụ: ```js run let arr = [1, 2, 3, 4, 5]; @@ -430,15 +430,13 @@ arr.reverse(); alert( arr ); // 5,4,3,2,1 ``` -It also returns the array `arr` after the reversal. - -### split and join +Nó trả về `arr` sau khi đã đảo thứ tự. -Here's the situation from the 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? +### split và join -The [str.split(delim)](mdn:js/String/split) method does exactly that. It splits the string into an array by the given delimiter `delim`. +method [str.split(delim)](mdn:js/String/split) phân tách các string vào một array bởi sự phân cách `delim`. -In the example below, we split by a comma followed by space: +Trong ví dụ dưới ta tách string bởi 1 dấu phẩy và 1 dấu space: ```js run let names = 'Bilbo, Gandalf, Nazgul'; @@ -450,7 +448,7 @@ for (let name of arr) { } ``` -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: +`split` method có một tham số tùy chọn là một number -- giới hạn của array length. Nếu được truyền vào, sẽ bõ qua các element khi array đã đủ số element: ```js run let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); @@ -458,8 +456,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="Split thành các chữ cái" +Gọi `split('')` sẽ tách từng chữ vào trong array: ```js run let str = "test"; @@ -468,9 +466,9 @@ alert( str.split('') ); // t,e,s,t ``` ```` -The call [arr.join(str)](mdn:js/Array/join) does the reverse to `split`. It creates a string of `arr` items glued by `str` between them. +Method [arr.join(str)](mdn:js/Array/join) ngược lại với `split`. Nó tạo ra string từ các `arr` items với dấu phân cách là `str`. -For instance: +Ví dụ: ```js run let arr = ['Bilbo', 'Gandalf', 'Nazgul']; @@ -482,13 +480,13 @@ alert( str ); // Bilbo;Gandalf;Nazgul ### reduce/reduceRight -When we need to iterate over an array -- we can use `forEach`. +Khi ta lặp (iterate) qua một array -- ta có thể dùng `forEach`. -When we need to iterate and return the data for each element -- we can use `map`. +Khi ta muốn lặp và trả về data theo mỗi element -- ta 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. +Methods [arr.reduce](mdn:js/Array/reduce) và [arr.reduceRight](mdn:js/Array/reduceRight) cũng tương tự như thế, nhưng là một chút phức tạp hơn. Chúng được sử dụng để tính toán một giá trị đơn dựa trên mảng. -The syntax is: +Cú pháp: ```js let value = arr.reduce(function(previousValue, item, index, arr) { @@ -496,19 +494,19 @@ let value = arr.reduce(function(previousValue, item, index, arr) { }, initial); ``` -The function is applied to the elements. You may notice the familiar arguments, starting from the 2nd: +Hàm được áp dụng cho các elements. Bạn nên chú ý, tham số hay dùng bắt đầu từ vị trí thứ 2: -- `item` -- is the current array item. -- `index` -- is its position. -- `arr` -- is the array. +- `item` -- array item. +- `index` -- index của item. +- `arr` -- chính là array. -So far, like `forEach/map`. But there's one more argument: +Vẫn tương tự `forEach/map`. nhưng có thêm tham số: -- `previousValue` -- is the result of the previous function call, `initial` for the first call. +- `previousValue` -- là kết quả của function call trước đó, `initial` khởi tạo cho lần function call đầu tiên. -The easiest way to grasp that is by example. +Cách dễ nhất để nắm bắt đó là bằng ví dụ. -Here we get a sum of array in one line: +Ở đây ta tính tổng của một mảng: ```js run let arr = [1, 2, 3, 4, 5] @@ -518,19 +516,19 @@ let result = arr.reduce((sum, current) => sum + current, 0); alert(result); // 15 ``` -Here we used the most common variant of `reduce` which uses only 2 arguments. +Ở đây chúng tôi đã sử dụng biến thể phổ biến nhất của `reduce` với chỉ hai tham số. -Let's see the details of what's going on. +Chúng ta xem chuyện gì 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 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 ot it, and so on... +1. Lần đầu chạy, `sum` là có giá trị khởi tạo - initial (tham số cuối cùng trong `reduce`), bằng `0`, và `current` là element đầu tiên của arr, bằng `1`. Nên kết quả là `1`, gán cho `sum` +2. Lần thứ hai chạy, `sum = 1`, Ta cộng với element thứ hai là `2` , kết quả là `3`, gán cho `sum` +3. Lần thứ ba chạy, `sum = 3` ... -The calculation flow: +Sơ đồ: ![](reduce.png) -Or in the form of a table, where each row represents is a function call on the next array element: +Hoặc xem bảng: | |`sum`|`current`|`result`| |---|-----|---------|---------| @@ -541,9 +539,9 @@ Or in the form of a table, where each row represents is a function call on the n |the fifth call|`10`|`5`|`15`| -As we can see, the result of the previous call becomes the first argument of the next one. +Ta có thể thấy kết quả của lần gọi trước là tham số của lần gọi tiếp theo. -We also can omit the initial value: +Ta có thể bõ qua giá trị khởi tạo: ```js run let arr = [1, 2, 3, 4, 5]; @@ -554,7 +552,7 @@ 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ả vẫn thế. Bởi vì nếu không có giá trị khởi tạo, thì `reduce` lấy giá trị element đầu tiên làm giá trị khởi tạo, và lặp tiếp từ element thứ hai. The calculation table is the same as above, minus the first row. From f6ff69b44b907bd3dc7e069d62fe3832b2c2e6ff Mon Sep 17 00:00:00 2001 From: Son Tran Date: Tue, 14 Nov 2017 21:09:33 +0700 Subject: [PATCH 78/78] Update article.md --- .../05-data-types/05-array-methods/article.md | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) 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 576a57b0d3..876583bd73 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -378,8 +378,6 @@ alert(arr); // *!*1, 2, 15*/!* Bây giờ nó hoạt động như mong muốn. -Let's step aside and think what's happening. The `arr` can be array of anything, right? It may contain numbers or strings or html elements or whatever. We have a set of *something*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order. - Method `arr.sort(fn)` tự thực hiện các thuật toán phân loại. Ta không cần quan tâm nó hoạt động bằng cách nào (Một cách sắp xếp tối ưu [quicksort](https://en.wikipedia.org/wiki/Quicksort) hầu hết thời gian). Nó sẽ lướt qua array, thực hiện các phép so sánh theo hàm `fn` mà ta cung cấp để thực hiện các phép so sánh. Nhân tiện, nếu chúng ta muốn biết những element nào được so sánh -- không có gì xuất hiện khi alert chúng: @@ -554,11 +552,9 @@ alert( result ); // 15 Kết quả vẫn thế. Bởi vì nếu không có giá trị khởi tạo, thì `reduce` lấy giá trị element đầu tiên làm giá trị khởi tạo, và lặp tiếp từ element thứ hai. -The calculation table is the same as above, minus the first row. - -But such use requires an extreme care. If the array is empty, then `reduce` call without initial value gives an error. +Chý ý nếu `arr` là rỗng, thì `reduce` sẽ lỗi nếu không thiết lập giá trị khởi tạo. -Here's an example: +Ví dụ: ```js run let arr = []; @@ -569,30 +565,30 @@ arr.reduce((sum, current) => sum + current); ``` -So it's advised to always specify the initial value. +Tốt nhất là nên thiết lập giá trị khởi tạo. -The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left. +Method [arr.reduceRight](mdn:js/Array/reduceRight) cũng tương tự như vậy nhưng thực hiện từ phải sang trái. ## Iterate: forEach -The [arr.forEach](mdn:js/Array/forEach) method allows to run a function for every element of the array. +Method [arr.forEach](mdn:js/Array/forEach) cho phép gọi một hàm với mỗi element của array. -The syntax: +Cú pháp: ```js arr.forEach(function(item, index, array) { // ... do something with item }); ``` -For instance, this shows each element of the array: +Ví dụ show mỗi element của array: ```js run // for each element call alert ["Bilbo", "Gandalf", "Nazgul"].forEach(alert); ``` -And this code is more elaborate about their positions in the target array: +Hay phức tạp hơn: ```js run ["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => { @@ -600,20 +596,20 @@ And this code is more elaborate about their positions in the target array: }); ``` -The result of the function (if it returns any) is thrown away and ignored. +Kết quả của hàm sẽ bị bõ đi (hàm return cái gì cũng không quan tâm). ## Array.isArray -Arrays do not form a separate language type. They are based on objects. +Arrays Không phải là một kiểu riêng. Chúng cũng là objects. -So `typeof` does not help to distinguish a plain object from an array: +nên `typeof` không giúp ta phân biệt được một array hay không: ```js run alert(typeof {}); // object alert(typeof []); // same ``` -...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ó một method để kiểm tra: [Array.isArray(value)](mdn:js/Array/isArray). Nó trả về `true` nếu `value` thực sự là array, và `false` ngược lại. ```js run alert(Array.isArray({})); // false @@ -621,13 +617,13 @@ alert(Array.isArray({})); // false alert(Array.isArray([])); // true ``` -## Most methods support "thisArg" +## "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 hết các array method mà có gọi hàm -- như `find`, `filter`, `map`, với một ngoại lệ là `sort`, chấp nhận tham số 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ố này ta chưa học, vì thực sự nó ít khi được dùng. Nhưng để cho hoàn thiện, ta nên biết về nó. -Here's the full syntax of these methods: +Đây là cú pháp đầy đủ: ```js arr.find(func, thisArg); @@ -637,9 +633,9 @@ arr.map(func, thisArg); // thisArg is the optional last argument ``` -The value of `thisArg` parameter becomes `this` for `func`. +Giá trị của tham số `thisArg` là `this` cho `func`. -For instance, here we use an object method as a filter and `thisArg` comes in handy: +Ví dụ ta dùng một object method để làm hàm filter và `thisArg` sẽ dùng cho việc này: ```js run let user = { @@ -663,13 +659,13 @@ let youngerUsers = users.filter(user.younger, user); alert(youngerUsers.length); // 2 ``` -In the call above, we use `user.younger` as a filter and also provide `user` as the context for it. If we didn't provide the context, `users.filter(user.younger)` would call `user.younger` as a standalone function, with `this=undefined`. That would mean an instant error. +Ta dùng `user.younger` như một hàm filter và cung cấp `user` như một ngữ cảnh cho nó. Nếu không có ngữ cảnh, `users.filter(user.younger)` sẽ gọi `user.younger` như một standalone function, với `this=undefined`. -## Summary +## Tổng kết -A cheatsheet of array methods: +Một cheatsheet cho array methods: -- To add/remove elements: +- Để add/remove elements: - `push(...items)` -- adds items to the end, - `pop()` -- extracts an item from the end, - `shift()` -- extracts an item from the beginning,