From e34ab53211824f303120bf1d4eb2c6a6e35c8919 Mon Sep 17 00:00:00 2001 From: Henry Bui Date: Thu, 7 May 2020 22:52:47 +0700 Subject: [PATCH 1/2] Translate article to Vietnamese --- 1-js/02-first-steps/07-operators/article.md | 444 -------------------- 1-js/02-first-steps/08-operators/article.md | 443 +++++++++++++++++++ 2 files changed, 443 insertions(+), 444 deletions(-) delete mode 100644 1-js/02-first-steps/07-operators/article.md create mode 100644 1-js/02-first-steps/08-operators/article.md diff --git a/1-js/02-first-steps/07-operators/article.md b/1-js/02-first-steps/07-operators/article.md deleted file mode 100644 index 965cde936..000000000 --- a/1-js/02-first-steps/07-operators/article.md +++ /dev/null @@ -1,444 +0,0 @@ -# Operators - -We know many operators from school. They are things like addition `+`, multiplication `*`, subtraction `-`, and so on. - -In this chapter, we'll concentrate on aspects of operators that are not covered by school arithmetic. - -## Terms: "unary", "binary", "operand" - -Before we move on, let's grasp some common terminology. - -- *An operand* -- is what operators are applied to. For instance, in the multiplication of `5 * 2` there are two operands: the left operand is `5` and the right operand is `2`. Sometimes, people call these "arguments" instead of "operands". -- An operator is *unary* if it has a single operand. For example, the unary negation `-` reverses the sign of a number: - - ```js run - let x = 1; - - *!* - x = -x; - */!* - alert( x ); // -1, unary negation was applied - ``` -- An operator is *binary* if it has two operands. The same minus exists in binary form as well: - - ```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). - -## String concatenation, binary + - -Now, let's see special features of JavaScript operators that are beyond school arithmetics. - -Usually, the plus operator `+` sums numbers. - -But, if the binary `+` is applied to strings, it merges (concatenates) them: - -```js -let s = "my" + "string"; -alert(s); // mystring -``` - -Note that if one of the operands is a string, the other one is converted to a string too. - -For example: - -```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, the other one is converted into a string as well. - -However, note that operations run from left to right. If there are two numbers followed by a string, the numbers will be added before being converted to a string: - - -```js run -alert(2 + 2 + '1' ); // "41" and not "221" -``` - -String concatenation and conversion is a special feature of the binary plus `+`. Other arithmetic operators work only with numbers and always convert their operands to numbers. - -For instance, subtraction and division: - -```js run -alert( 2 - '1' ); // 1 -alert( '6' / '2' ); // 3 -``` - -## Numeric conversion, unary + - -The plus `+` exists in two forms: the binary form that we used above and the unary form. - -The unary plus or, in other words, the plus operator `+` applied to a single value, doesn't do anything to numbers. But if the operand is not a number, the unary plus converts it into a number. - -For example: - -```js run -// No effect on numbers -let x = 1; -alert( +x ); // 1 - -let y = -2; -alert( +y ); // -2 - -*!* -// Converts non-numbers -alert( +true ); // 1 -alert( +"" ); // 0 -*/!* -``` - -It actually does the same thing as `Number(...)`, but is shorter. - -The need to convert strings to numbers arises very often. For example, if we are getting values from HTML form fields, they are usually strings. What if we want to sum them? - -The binary plus would add them as strings: - -```js run -let apples = "2"; -let oranges = "3"; - -alert( apples + oranges ); // "23", the binary plus concatenates strings -``` - -If we want to treat them as numbers, we need to convert and then sum them: - -```js run -let apples = "2"; -let oranges = "3"; - -*!* -// both values converted to numbers before the binary plus -alert( +apples + +oranges ); // 5 -*/!* - -// the longer variant -// 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. - -Why are unary pluses applied to values before the binary ones? As we're going to see, that's because of their *higher precedence*. - -## Operator precedence - -If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, the default priority order of operators. - -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. - -Parentheses override any precedence, so if we're not satisfied with the default order, we can use them to change it. For example, write `(1 + 2) * 2`. - -There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the larger number executes first. If the precedence is the same, the execution order is from left to right. - -Here's 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): - -| Precedence | Name | Sign | -|------------|------|------| -| ... | ... | ... | -| 16 | unary plus | `+` | -| 16 | unary negation | `-` | -| 14 | multiplication | `*` | -| 14 | division | `/` | -| 13 | addition | `+` | -| 13 | subtraction | `-` | -| ... | ... | ... | -| 3 | assignment | `=` | -| ... | ... | ... | - -As we can see, the "unary plus" has a priority of `16` which is higher than the `13` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition. - -## Assignment - -Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `3`. - -That's why, when we assign a variable, like `x = 2 * 2 + 1`, the calculations are done first and then the `=` is evaluated, storing the result in `x`. - -```js -let x = 2 * 2 + 1; - -alert( x ); // 5 -``` - -It is possible to chain assignments: - -```js run -let a, b, c; - -*!* -a = b = c = 2 + 2; -*/!* - -alert( a ); // 4 -alert( b ); // 4 -alert( c ); // 4 -``` - -Chained assignments evaluate from right to left. First, the rightmost expression `2 + 2` is evaluated and then assigned to the variables on the left: `c`, `b` and `a`. At the end, all the variables share a single value. - -````smart header="The assignment operator `\"=\"` returns a value" -An operator always returns a value. That's obvious for most of them like addition `+` or multiplication `*`. But the assignment operator follows this rule too. - -The call `x = value` writes the `value` into `x` *and then returns it*. - -Here's a demo that uses an assignment as part of a more complex expression: - -```js run -let a = 1; -let b = 2; - -*!* -let c = 3 - (a = b + 1); -*/!* - -alert( a ); // 3 -alert( c ); // 0 -``` - -In the example above, the result of expression `(a = b + 1)` is the value which was assigned to `a` (that is `3`). It is then used for further evaluations. - -Funny code, isn't it? We should understand how it works, because sometimes we see it in JavaScript libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make code clearer or readable. -```` - -## Remainder % - -The remainder operator `%`, despite its appearance, is not related to percents. - -The result of `a % b` is the remainder of the integer division of `a` by `b`. - -For instance: - -```js run -alert( 5 % 2 ); // 1 is a remainder of 5 divided by 2 -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 ** - -The exponentiation operator `**` is a recent addition to the language. - -For a natural number `b`, the result of `a ** b` is `a` multiplied by itself `b` times. - -For instance: - -```js run -alert( 2 ** 2 ); // 4 (2 * 2) -alert( 2 ** 3 ); // 8 (2 * 2 * 2) -alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2) -``` - -The operator works for non-integer numbers as well. - -For instance: - -```js run -alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths) -alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root) -``` - -## Increment/decrement - - - -Increasing or decreasing a number by one is among the most common numerical operations. - -So, there are special operators for it: - -- **Increment** `++` increases a variable by 1: - - ```js run no-beautify - let counter = 2; - counter++; // works the same as counter = counter + 1, but is shorter - alert( counter ); // 3 - ``` -- **Decrement** `--` decreases a variable by 1: - - ```js run no-beautify - let counter = 2; - counter--; // works the same as counter = counter - 1, but is shorter - alert( counter ); // 1 - ``` - -```warn -Increment/decrement can only be applied to variables. Trying to use it on a value like `5++` will give an error. -``` - -The operators `++` and `--` can be placed either before or after a variable. - -- When the operator goes after the variable, it is in "postfix form": `counter++`. -- The "prefix form" is when the operator goes before the variable: `++counter`. - -Both of these statements do the same thing: increase `counter` by `1`. - -Is there any difference? Yes, but we can only see it if we use the returned value of `++/--`. - -Let's clarify. As we know, all operators return a value. Increment/decrement is no exception. The prefix form returns the new value while the postfix form returns the old value (prior to increment/decrement). - -To see the difference, here's an example: - -```js run -let counter = 1; -let a = ++counter; // (*) - -alert(a); // *!*2*/!* -``` - -In the line `(*)`, the *prefix* form `++counter` increments `counter` and returns the new value, `2`. So, the `alert` shows `2`. - -Now, let's use the postfix form: - -```js run -let counter = 1; -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`. - -To summarize: - -- If the result of increment/decrement is not used, there is no difference in which form to use: - - ```js run - let counter = 0; - counter++; - ++counter; - alert( counter ); // 2, the lines above did the same - ``` -- If we'd like to increase a value *and* immediately use the result of the operator, we need the prefix form: - - ```js run - let counter = 0; - alert( ++counter ); // 1 - ``` -- If we'd like to increment a value but use its previous value, we need the postfix form: - - ```js run - let counter = 0; - alert( counter++ ); // 0 - ``` - -````smart header="Increment/decrement among other operators" -The operators `++/--` can be used inside expressions as well. Their precedence is higher than most other arithmetical operations. - -For instance: - -```js run -let counter = 1; -alert( 2 * ++counter ); // 4 -``` - -Compare with: - -```js run -let counter = 1; -alert( 2 * counter++ ); // 2, because counter++ returns the "old" value -``` - -Though technically okay, such notation usually makes code less readable. One line does multiple things -- not good. - -While reading code, a fast "vertical" eye-scan can easily miss something like `counter++` and it won't be obvious that the variable increased. - -We advise a style of "one line -- one action": - -```js run -let counter = 1; -alert( 2 * counter ); -counter++; -``` -```` - -## Bitwise operators - -Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their binary representation. - -These operators are not JavaScript-specific. They are supported in most programming languages. - -The list of operators: - -- AND ( `&` ) -- OR ( `|` ) -- XOR ( `^` ) -- NOT ( `~` ) -- LEFT SHIFT ( `<<` ) -- RIGHT SHIFT ( `>>` ) -- ZERO-FILL RIGHT SHIFT ( `>>>` ) - -These operators are used very rarely. To understand them, we need to delve into low-level number representation and it would not be optimal to do that right now, especially since 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 on MDN. It would be more practical to do that when a real need arises. - -## Modify-in-place - -We often need to apply an operator to a variable and store the new result in that same variable. - -For example: - -```js -let n = 2; -n = n + 5; -n = n * 2; -``` - -This notation can be shortened using the operators `+=` and `*=`: - -```js run -let n = 2; -n += 5; // now n = 7 (same as n = n + 5) -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. - -Such operators have the same precedence as a normal assignment, so they run after most other calculations: - -```js run -let n = 2; - -n *= 3 + 5; - -alert( n ); // 16 (right part evaluated first, same as n *= 8) -``` - -## Comma - -The comma operator `,` is one of the rarest and most unusual operators. Sometimes, it's used to write shorter code, so we need to know it in order to understand what's going on. - -The comma operator allows us to evaluate several expressions, dividing them with a comma `,`. Each of them is evaluated but only the result of the last one is returned. - -For example: - -```js run -*!* -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. - -```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. - -Without them: `a = 1 + 2, 3 + 4` evaluates `+` first, summing the numbers into `a = 3, 7`, then the assignment operator `=` assigns `a = 3`, and the rest is ignored. It's like `(a = 1 + 2), 3 + 4`. -``` - -Why do we need an operator that throws away everything except the last expression? - -Sometimes, people use it in more complex constructs to put several actions in one line. - -For example: - -```js -// three operations in one line -for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) { - ... -} -``` - -Such tricks are used in many JavaScript frameworks. That's why we're mentioning them. But usually they don't improve code readability so we should think well before using them. diff --git a/1-js/02-first-steps/08-operators/article.md b/1-js/02-first-steps/08-operators/article.md new file mode 100644 index 000000000..76eab1328 --- /dev/null +++ b/1-js/02-first-steps/08-operators/article.md @@ -0,0 +1,443 @@ +# Các toán tử + +Chúng ta đã biết rất nhiều toán tử từ học đường. Chúng là những thứ như cộng `+`, nhân `*`, trừ `-`, và các toán tử khác. + +Trong chương này, chúng ta sẽ tập trung vào các khía cạnh của các toán tử không được bao gồm trong môn số học của học đường. + +## Số hạng: "đơn nguyên", "nhị phân", "toán hạng" + +Trước khi tiếp tục, hãy nắm bắt một số thuật ngữ phổ biến. + +- *Toán hạng* -- áp dụng cho các toán tử. Chẳng hạn, trọng phép nhân của `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`. Đôi khi, mọi người gọi là những "đối số" thay vì "toán hạng". +- Một toán hạng là *đơn nguyên* nếu nó có một toán hạng đơn. Ví dụ: phủ định đơn nguyên `-` đảo ngược dấu của một số: + + ```js run + let x = 1; + + *!* + x = -x; + */!* + alert( x ); // -1, phủ định đơn nguyên được áp dụng + ``` +- Một toán tử là *nhị phân* nếu nó có hai toán hạng. Dấu trừ tương tự cũng tồn tại ở dạng nhị phân: + + ```js run no-beautify + let x = 1, y = 3; + alert( y - x ); // 2, trừ nhị phân trừ đi các giá trị + ``` + + Chính thức, chúng ta đang nói về hai toán tử khác nhau ở đây: phủ định đơn nguyên (toán hạng đơn: đảo ngược dấu) và phép trừ nhị phân (hai toán hạng: phép trừ). + +## Nối chuỗi, nhị phân + + +Bây giờ, chúng ta hãy xem các tính năng đặc biệt của các toán tử JavaScript nằm ngoài phạm vi của học đường. + +Thông thường, toán tử cộng `+` dùng để cộng hai số. + +Nhưng, nếu trong nhị phân `+` được dùng cho chuỗi, nó nối (tiếp) chúng: + +```js +let s = "my" + "string"; +alert(s); // mystring +``` + +Nhớ rằng nếu một toán tử là chuỗi, toán tử còn lại cũng sẽ được chuyển đổi thành một chuỗi. + +Ví dụ: + +```js run +alert( '1' + 2 ); // "12" +alert( 2 + '1' ); // "21" +``` + +Thấy không, nó không quan trọng toán tử đầu tiên hay thứ hai là chuỗi. Luật ở đây rất đơn giản: nếu một trong hai toán tử là chuỗi, toán tử còn lại cũng sẽ được chuyển thành chuỗi. + +Tuy nhiên, nhớ rằng các toán tử được đọc từ trái sang phải. Nếu có hai số được theo sau bởi một chuỗi, các số đó sẽ được cộng trước khi được chuyển đổi thành một chuỗi: + + +```js run +alert(2 + 2 + '1' ); // "41" chứ không phải "221" +``` + +Nối chuỗi và chuyển đổi chuỗi là một tính năng đặc biệt của cộng nhị phân `+`. Các toán tử số học khác chỉ làm việc với các số và luôn chuyển đổi toán hạng của chúng thành các số. + +Ví dụ, phép trừ và phép chia: + +```js run +alert( 2 - '1' ); // 1 +alert( '6' / '2' ); // 3 +``` + +## Chuyển đổi số, đơn nguyên + + +Dấu cộng `+` tồn tại ở hai dạng: dạng nhị phân chúng ta đã dùng ở trên và dạng đơn nguyên. + +Cộng đơn nguyên, hay nói cách khác, toán tử cộng `+` áp dụng cho giá trị đơn, không đụng gì đến các số. Nhưng nếu toán hạng không phải là một số, thì dấu cộng đơn nguyên sẽ chuyển nó thành một số. + +Ví dụ: + +```js run +// Không đụng đến số +let x = 1; +alert( +x ); // 1 + +let y = -2; +alert( +y ); // -2 + +*!* +// Chuyển đổi những thứ không phải số +alert( +true ); // 1 +alert( +"" ); // 0 +*/!* +``` + +Nó làm điều tương tự như là `Number(...)`, nhưng ngắn hơn. + +Nhu cầu chuyển đổi chuỗi thành số phát sinh rất thường xuyên. Ví dụ: nếu chúng ta đang nhận các giá trị từ các trường nhập liệu HTML, thì chúng thường là các chuỗi. Nếu chúng ta muốn cộng chúng thì sao? + +Cộng nhị phân sẽ cộng chúng như là các chuỗi: + +```js run +let apples = "2"; +let oranges = "3"; + +alert( apples + oranges ); // "23", cộng nhị nhân nối chuỗi +``` + +Nếu ta muốn xem chúng như là các số, ta cần biến đổi chúng và sau đó cộng: + +```js run +let apples = "2"; +let oranges = "3"; + +*!* +// cả hai giá trị được chuyển đổi sang số trước khi cộng nhị phân +alert( +apples + +oranges ); // 5 +*/!* + +// biến thể dài hơn +// alert( Number(apples) + Number(oranges) ); // 5 +``` + +Từ quan điểm của một nhà toán học, sự phong phú của các phép cộng có vẻ lạ. Nhưng theo quan điểm của một lập trình viên, không có gì đặc biệt: các phép cộng đơn được áp dụng trước tiên, họ chuyển đổi chuỗi thành số và sau đó phép cộng nhị phân cộng chúng lại. + +Tại sao các phép cộng đơn nguyên được áp dụng cho các giá trị trước các giá trị nhị phân? Như chúng ta thấy, đó là vì *sự ưu tiên cao hơn* của nó. + +## Toán tử ưu tiên + +Nếu một biểu thức có nhiều toán tử, thứ tự thực hiện được xác định bởi *độ ưu tiên* của chúng, hay nói cách khác, thứ tự ưu tiên mặc định của các toán tử. + +Từ trường học, tất cả chúng ta đều biết rằng phép nhân trong biểu thức `1 + 2 * 2` nên được tính trước khi cộng. Đó chính xác là độ ưu tiên. Phép nhân được cho là có *độ ưu tiên cao hơn* phép cộng. + +Dấu ngoặc đơn ghi đè bất kỳ quyền ưu tiên nào, vì vậy nếu chúng ta không hài lòng với thứ tự mặc định, chúng ta có thể sử dụng chúng để thay đổi. Ví dụ, viết `(1 + 2) * 2`. + +Có nhiều toán tử trong JavaScript. Mỗi toán tử có một số ưu tiên tương ứng. Cái có số lượng lớn hơn được thực hiện đầu tiên. Nếu quyền ưu tiên là như nhau, thứ tự thực hiện là từ trái sang phải. + +Đây là đoạn trích từ [bảng độ ưu tiên](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (bạn không cần phải nhớ nó, nhưng nhớ rằng các toán tử đơn nguyên có độ ưu tiên cao hơn các toán tử nhị phân): + +| Độ ưu tiên | Tên | Kí hiệu | +|------------|------|------| +| ... | ... | ... | +| 16 | cộng đơn nguyên | `+` | +| 16 | trừ đơn nguyên | `-` | +| 14 | nhân | `*` | +| 14 | chia | `/` | +| 13 | cộng | `+` | +| 13 | trừ | `-` | +| ... | ... | ... | +| 3 | gán | `=` | +| ... | ... | ... | + +Như chúng ta thấy, phép "cộng đơn nguyên" có độ ưu tiên là `16` cao hơn `13` của phép "cộng" (cộng nhị phân). Đó là lý do, trong biểu thức `"+apples + +oranges"`, cộng đơn nguyên chạy trước cộng nhị phân. + +## Phép gán + +Hãy lưu ý rằng một phép gán `=` cũng là một toán tử. Nó được liệt kê trong bảng ưu tiên với mức ưu tiên rất thấp là `3`. + +Đó là lý do tại sao, khi chúng ta gán một biến, như `x = 2 * 2 + 1`, các phép tính được thực hiện trước và sau đó dấu ` = `được chạy, lưu trữ kết quả trong` x`. + +```js +let x = 2 * 2 + 1; + +alert( x ); // 5 +``` + +Có thể xâu chuỗi các phép gán: + +```js run +let a, b, c; + +*!* +a = b = c = 2 + 2; +*/!* + +alert( a ); // 4 +alert( b ); // 4 +alert( c ); // 4 +``` + +Chuỗi các phép gán được xác định từ phải sang trái. Đầu tiên, biểu thức ngoài cùng bên phải `2 + 2` được ước tính và sau đó được gán cho các biến ở bên trái:` c`, `b` và` a`. Cuối cùng, tất cả các biến chia sẻ một giá trị duy nhất. + +````smart header="Toán tử phép gán `\"=\"` trả về một giá trị" +Một toán tử luôn luôn trả về một giá trị. Điều đó rõ ràng đối với hầu hết trong số chúng như phép cộng `+` hoặc phép nhân `*`. Nhưng toán tử gán cũng tuân theo quy tắc này. + +Gọi `x = value` nghĩa là gán `value` vào `x` *và sau đó trả về nó*. + +Đây là demo sử dụng một phép gán như một phần của biểu thức phức tạp hơn: + +```js run +let a = 1; +let b = 2; + +*!* +let c = 3 - (a = b + 1); +*/!* + +alert( a ); // 3 +alert( c ); // 0 +``` + +Trong ví dụ trên, kết quả của biểu thức `(a = b + 1)` được gán cho `a` (đó là `3`). Sau đó nó được sử dụng tiếp để tính toán. + +Lập trình thật hài hước, phải không? Chúng ta nên hiểu cách thức hoạt động của nó, bởi vì đôi khi chúng ta thấy nó trong các thư viện JavaScript, nhưng đừng nên tự viết bất cứ thứ gì như thế. Viết như vậy chắc chắn không làm cho code rõ ràng hơn hay dễ đọc hơn. + +## Phần dư % + +Toán tử phần dư `%`, mặt dù sự xuất hiện của nó, không liên quan đến phần trăm. + +Kết quả của `a % b` là phần dư phép chia số nguyên của `a` cho `b`. + +Ví dụ: + +```js run +alert( 5 % 2 ); // 1 là phần dư của 5 chia cho 2 +alert( 8 % 3 ); // 2 là phần dư của 8 chia cho 3 +alert( 6 % 3 ); // 0 là phần dư của 6 chia cho 3 +``` + +## Lũy thừa ** + +Toán tử lũy thừa `**` là phần mới được thêm vào ngôn ngữ gần đây. + +Cho một số tự nhiên `b`, kết quả của `a ** b` là `a` nhân với chính nó `b` lần. + +Ví dụ: + +```js run +alert( 2 ** 2 ); // 4 (2 * 2) +alert( 2 ** 3 ); // 8 (2 * 2 * 2) +alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2) +``` + +Toán tử này cũng hoạt động với số không phải số nguyên. + +Ví dụ: + +```js run +alert( 4 ** (1/2) ); // 2 (lũy thừa của 1/2 giống như căn bậc hai, đó là toán học) +alert( 8 ** (1/3) ); // 2 (lũy thừa 1/3 giống như căn bậc ba) +``` + +## Phép tăng/phép giảm + + + +Tăng hoặc giảm một số là một trong những thao tác số phổ biến nhất. + +Vì vậy, có các toán tử đặc biệt cho nó: + +- **Phép tăng** `++` tăng giá trị của biến thêm 1: + + ```js run no-beautify + let counter = 2; + counter++; // hoạt động như counter = counter + 1, nhưng ngắn hơn + alert( counter ); // 3 + ``` +- **Phép giảm** `--` giảm giá trị của biến đi 1: + + ```js run no-beautify + let counter = 2; + counter--; // hoạt động như counter = counter - 1, nhưng ngắn hơn + alert( counter ); // 1 + ``` + +```warn +Phép tăng/phép giảm chỉ có thể được áp dụng cho các biến. Nếu sử dụng nó trên một giá trị như `5++` sẽ báo lỗi. +``` + +Toán tử `++` và `--` có thể được đặt trước hoặc sau một biến. + +- Khi toán tử đi sau biến, nó ở "dạng hậu tố": `counter++`. +- "Dạng tiền tố" là khi toán tử đi trước biến: `++counter`. + +Cả hai câu lệnh này đều làm cùng một điều: tăng `counter` lên `1`. + +Có gì khác biệt không? Có, nhưng chúng ta chỉ thấy chúng nếu ta sử dụng giá trị trả về của `++/--`. + +Hãy làm rõ. Như chúng ta biết, tất cả các toán tử đều trả về một giá trị. Phép tăng/phép giảm cũng không ngoại lệ. Dạng tiền tố trả về giá trị mới trong khi dạng hậu tố trả về giá trị cũ (trước khi tăng/giảm). + +Để thấy sự khác biệt, xem ví dụ sau: + +```js run +let counter = 1; +let a = ++counter; // (*) + +alert(a); // *!*2*/!* +``` + +Trong dòng `(*)`, dạng *tiền tố* `++counter` tăng `counter` và trả về giá trị mới, `2`. Vì vậy, hàm `alert` sẽ hiển thị `2`. + +Giờ, hãy sử dụng dạng hậu tố: + +```js run +let counter = 1; +let a = counter++; // (*) thay đổi ++counter sang counter++ + +alert(a); // *!*1*/!* +``` + +Trong dòng `(*)`, dạng *hậu tố* `counter++` cũng tăng `counter` nhưng trả về giá trị *cũ* (trước khi tăng). Do đó, hàm `alert` sẽ hiển thị `1`. + +Tóm tắt: + +- Nếu kết quả tăng/giảm không được sử dụng, sẽ không có sự khác biệt trong các dạng được sử dụng: + + ```js run + let counter = 0; + counter++; + ++counter; + alert( counter ); // 2, những dòng phía trên đều giống nhau + ``` +- Nếu chúng ta muốn tăng giá trị *và* ngay lập tức sử dụng kết quả của toán tử, chúng ta cần dạng tiền tố: + + ```js run + let counter = 0; + alert( ++counter ); // 1 + ``` +- Nếu chúng ta muốn tăng giá trị * và * muốn sử dụng kết quả trước của nó, chúng ta cần dạng hậu tố: + + ```js run + let counter = 0; + alert( counter++ ); // 0 + ``` + +````smart header="Tăng/giảm giữa các toán tử khác" +Toán tử `++/--` cũng có thể được sử dụng trong các biểu thức. Ưu tiên của nó cao hơn hầu hết các toán tử số học khác. + +Ví dụ: + +```js run +let counter = 1; +alert( 2 * ++counter ); // 4 +``` + +So sánh với: + +```js run +let counter = 1; +alert( 2 * counter++ ); // 2, vì counter++ trả về giá trị "cũ" +``` + +Mặc dù không sai về mặt kỹ thuật, ký hiệu như vậy thường làm cho code khó đọc hơn. Làm nhiều việc trên một dòng - không tốt. + +Trong lúc đọc code, lướt mắt theo chiều "dọc" nhanh có thể khiến ta bỏ lỡ thứ gì đó như `counter++` và không biết rằng biến đã được tăng lên. + +Chúng tôi khuyến khích kiểu "mỗi dòng - một hành động": + +```js run +let counter = 1; +alert( 2 * counter ); +counter++; +``` +```` + +## Toán tử Bitwise + +Toán tử bitwise coi các đối số là số nguyên 32 bit và hoạt động ở mức độ biểu diễn nhị phân của chúng. + +Các toán tử này không dành riêng cho JavaScript. Chúng được hỗ trợ trong hầu hết các ngôn ngữ lập trình. + +Danh sách các toán tử: + +- AND ( `&` ) +- OR ( `|` ) +- XOR ( `^` ) +- NOT ( `~` ) +- LEFT SHIFT ( `<<` ) +- RIGHT SHIFT ( `>>` ) +- ZERO-FILL RIGHT SHIFT ( `>>>` ) + +Các toán tử này rất hiếm khi được sử dụng. Để hiểu chúng, chúng ta cần đi sâu vào biểu diễn số cấp thấp và không nên làm điều đó ngay bây giờ, đặc biệt vì chúng ta sẽ không cần chúng sớm. Nếu bạn tò mò, bạn có thể đọc [Toán tử Bitwise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) bài viết trên MDN. Sẽ thực tế hơn khi làm điều đó khi có nhu cầu thực sự. + +## Sửa đổi tại chỗ + +Chúng ta thường cần áp dụng một toán tử cho một biến và lưu trữ kết quả mới trong cùng một biến đó. + +Ví dụ: + +```js +let n = 2; +n = n + 5; +n = n * 2; +``` + +Ký hiệu này có thể được rút ngắn bằng cách sử dụng các toán tử `+=` và `*=`: + +```js run +let n = 2; +n += 5; // bây giờ n = 7 (giống như n = n + 5) +n *= 2; // bây giờ n = 14 (giống như n = n * 2) + +alert( n ); // 14 +``` + +Toán tử "sửa và gán" tồn tại cho tất cả các toán tử số học và bitwise: `/=`, `-=`, vâng vâng. + +Các toán tử như vậy có cùng mức ưu tiên như một phép gán thông thường, vì vậy chúng chạy sau hầu hết các phép tính khác: + +```js run +let n = 2; + +n *= 3 + 5; + +alert( n ); // 16 (phần bên phải được chạy đầu tiên, giống như n *= 8) +``` + +## Dấu phẩy + +Toán tử dấu phẩy `,` là một trong những toán tử hiếm nhất và bất thường nhất. Đôi khi, nó được sử dụng để viết code ngắn hơn, vì vậy chúng ta cần biết nó để hiểu những gì đang xảy ra. + +Toán tử dấu phẩy cho phép chúng ta chạy một số biểu thức, chia chúng bằng dấu phẩy `,`. Mỗi phần trong số chúng được chạy nhưng chỉ có kết quả của phần cuối cùng được trả về. + +Ví dụ: + +```js run +*!* +let a = (1 + 2, 3 + 4); +*/!* + +alert( a ); // 7 (kết quả của 3 + 4) +``` + +Đây, biểu thức đầu tiên `1 + 2` được chạy và kết quả của nó bị ném đi. Sau đó, `3 + 4` được chạy và trả về một kết quả. + +```smart header="Dấu phẩy có độ ưu tiên rất thấp" +Xin lưu ý rằng toán tử dấu phẩy có độ ưu tiên rất thấp, thấp hơn `=`, vì vậy dấu ngoặc đơn rất quan trọng trong ví dụ trên. + +Nếu không có chúng: `a = 1 + 2, 3 + 4` chạy `+` trước, tổng hợp các số thành `a = 3, 7`, sau đó phép gán `=` gán `a = 3`, và phần còn lại bị bỏ qua. Nó giống như `(a = 1 + 2), 3 + 4`. +``` + +Tại sao chúng ta cần một toán tử loại bỏ mọi thứ trừ biểu thức cuối cùng? + +Đôi khi, mọi người sử dụng nó trong các cấu trúc phức tạp hơn để đặt một số hành động trên một dòng. + +Ví dụ: + +```js +// ba toán tử trên một dòng +for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) { + ... +} +``` + +Các thủ thuật như vậy được sử dụng trong nhiều JavaScript frameworks. Đó là lý do tại sao chúng tôi đề cập đến chúng. Nhưng thường thì nó không cải thiện khả năng dễ đọc của code vì vậy chúng ta nên suy nghĩ kỹ trước khi sử dụng chúng. From aa05cd918d25f2cc4d606deafc11befe72c018ac Mon Sep 17 00:00:00 2001 From: Henry Bui Date: Thu, 7 May 2020 22:59:37 +0700 Subject: [PATCH 2/2] Translate tasks and solutions to Vietnamese --- .../07-operators/1-increment-order/solution.md | 18 ------------------ .../07-operators/1-increment-order/task.md | 14 -------------- .../2-assignment-result/solution.md | 5 ----- .../07-operators/2-assignment-result/task.md | 13 ------------- .../08-operators/1-increment-order/solution.md | 18 ++++++++++++++++++ .../08-operators/1-increment-order/task.md | 14 ++++++++++++++ .../2-assignment-result/solution.md | 5 +++++ .../08-operators/2-assignment-result/task.md | 13 +++++++++++++ 8 files changed, 50 insertions(+), 50 deletions(-) delete mode 100644 1-js/02-first-steps/07-operators/1-increment-order/solution.md delete mode 100644 1-js/02-first-steps/07-operators/1-increment-order/task.md delete mode 100644 1-js/02-first-steps/07-operators/2-assignment-result/solution.md delete mode 100644 1-js/02-first-steps/07-operators/2-assignment-result/task.md create mode 100644 1-js/02-first-steps/08-operators/1-increment-order/solution.md create mode 100644 1-js/02-first-steps/08-operators/1-increment-order/task.md create mode 100644 1-js/02-first-steps/08-operators/2-assignment-result/solution.md create mode 100644 1-js/02-first-steps/08-operators/2-assignment-result/task.md diff --git a/1-js/02-first-steps/07-operators/1-increment-order/solution.md b/1-js/02-first-steps/07-operators/1-increment-order/solution.md deleted file mode 100644 index 8a44d798e..000000000 --- a/1-js/02-first-steps/07-operators/1-increment-order/solution.md +++ /dev/null @@ -1,18 +0,0 @@ - -The answer is: - -- `a = 2` -- `b = 2` -- `c = 2` -- `d = 1` - -```js run no-beautify -let a = 1, b = 1; - -alert( ++a ); // 2, prefix form returns the new value -alert( b++ ); // 1, postfix form returns the old value - -alert( a ); // 2, incremented once -alert( b ); // 2, incremented once -``` - diff --git a/1-js/02-first-steps/07-operators/1-increment-order/task.md b/1-js/02-first-steps/07-operators/1-increment-order/task.md deleted file mode 100644 index 7db092389..000000000 --- a/1-js/02-first-steps/07-operators/1-increment-order/task.md +++ /dev/null @@ -1,14 +0,0 @@ -importance: 5 - ---- - -# The postfix and prefix forms - -What are the final values of all variables `a`, `b`, `c` and `d` after the code below? - -```js -let a = 1, b = 1; - -let c = ++a; // ? -let d = b++; // ? -``` diff --git a/1-js/02-first-steps/07-operators/2-assignment-result/solution.md b/1-js/02-first-steps/07-operators/2-assignment-result/solution.md deleted file mode 100644 index e3113b4cd..000000000 --- a/1-js/02-first-steps/07-operators/2-assignment-result/solution.md +++ /dev/null @@ -1,5 +0,0 @@ -The answer is: - -- `a = 4` (multiplied by 2) -- `x = 5` (calculated as 1 + 4) - diff --git a/1-js/02-first-steps/07-operators/2-assignment-result/task.md b/1-js/02-first-steps/07-operators/2-assignment-result/task.md deleted file mode 100644 index 5345c9485..000000000 --- a/1-js/02-first-steps/07-operators/2-assignment-result/task.md +++ /dev/null @@ -1,13 +0,0 @@ -importance: 3 - ---- - -# Assignment result - -What are the values of `a` and `x` after the code below? - -```js -let a = 2; - -let x = 1 + (a *= 2); -``` diff --git a/1-js/02-first-steps/08-operators/1-increment-order/solution.md b/1-js/02-first-steps/08-operators/1-increment-order/solution.md new file mode 100644 index 000000000..44b06e040 --- /dev/null +++ b/1-js/02-first-steps/08-operators/1-increment-order/solution.md @@ -0,0 +1,18 @@ + +Câu trả lời là: + +- `a = 2` +- `b = 2` +- `c = 2` +- `d = 1` + +```js run no-beautify +let a = 1, b = 1; + +alert( ++a ); // 2, dạng tiền tố trả về giá trị mới +alert( b++ ); // 1, dạng hậu tố trả về giá trị cũ + +alert( a ); // 2, tăng một lần +alert( b ); // 2, tăng một lần +``` + diff --git a/1-js/02-first-steps/08-operators/1-increment-order/task.md b/1-js/02-first-steps/08-operators/1-increment-order/task.md new file mode 100644 index 000000000..63de98d7d --- /dev/null +++ b/1-js/02-first-steps/08-operators/1-increment-order/task.md @@ -0,0 +1,14 @@ +importance: 5 + +--- + +# Dạng tiền tố và hậu tố + +Giá trị cuối cùng của tất cả các biến `a`,` b`, `c` và` d` ở đoạn code dưới đây là gì? + +```js +let a = 1, b = 1; + +let c = ++a; // ? +let d = b++; // ? +``` diff --git a/1-js/02-first-steps/08-operators/2-assignment-result/solution.md b/1-js/02-first-steps/08-operators/2-assignment-result/solution.md new file mode 100644 index 000000000..a5386edb2 --- /dev/null +++ b/1-js/02-first-steps/08-operators/2-assignment-result/solution.md @@ -0,0 +1,5 @@ +Câu trả lời là: + +- `a = 4` (được nhân với 2) +- `x = 5` (được tính như 1 + 4) + diff --git a/1-js/02-first-steps/08-operators/2-assignment-result/task.md b/1-js/02-first-steps/08-operators/2-assignment-result/task.md new file mode 100644 index 000000000..109379c89 --- /dev/null +++ b/1-js/02-first-steps/08-operators/2-assignment-result/task.md @@ -0,0 +1,13 @@ +importance: 3 + +--- + +# Kết quả gán + +Giá trị của `a` và `x` ở đoạn code dưới đây là gì? + +```js +let a = 2; + +let x = 1 + (a *= 2); +```