Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comparisons #32

Merged
merged 38 commits into from
Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a7d3a26
feat: translate comparison I
ArvinH Aug 31, 2019
27e634b
feat: translate comparison II
ArvinH Aug 31, 2019
c8aeab7
feat: complete translate comparison
ArvinH Aug 31, 2019
9bea300
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
627be4c
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
7cef081
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
66fecec
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
cbf8b08
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
ae19a1b
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
d859301
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
4ebc915
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
640c590
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
1f4b3df
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
de53f4e
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
3ed0cf6
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
3d208e0
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
20bd72e
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
da8f9ec
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
7862ba3
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
3e74a5d
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
9dd8cad
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
d92f6de
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
a2083b4
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
8f5c53e
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
7150940
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
1de64d4
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
38e69d2
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
6d58082
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
a3924d9
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
8fbe828
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
6311e57
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
3a817d3
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
edd02af
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
d14c8f1
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
495d5d8
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
b75aed1
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
036bbc3
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
c8a3abd
Update 1-js/02-first-steps/08-comparison/article.md
ArvinH Sep 1, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ null == "\n0\n" → false
null === +"\n0\n" → false
```

Some of the reasons:
答案解析:

1. Obviously, true.
2. Dictionary comparison, hence false.
3. Again, dictionary comparison, first char of `"2"` is greater than the first char of `"1"`.
4. Values `null` and `undefined` equal each other only.
5. Strict equality is strict. Different types from both sides lead to false.
6. Similar to `(4)`, `null` only equals `undefined`.
7. Strict equality of different types.
1. 數字間的大小比較,很顯然答案為 true
2. 按字典順序比較,因此為 false
3. 與上題相同,按字典順序比較,第一個字母 `"2"` 大於另一個字串的第一個字母 `"1"`
4. `null` `undefined` 彼此相等。
5. 嚴格比較下,比較不同類別的值會得到 false
6. 與`(4)` 相仿,`null` 只與 `undefined` 相等。
7. 嚴格比較下,不同類別的值會直接回傳 false。
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# Comparisons
# 值的比較

What will be the result for these expressions?
以下運算式的執行結果為何?

```js no-beautify
5 > 4
Expand Down
175 changes: 88 additions & 87 deletions 1-js/02-first-steps/08-comparison/article.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,95 @@
# Comparisons
# 值的比較

We know many comparison operators from maths:
我們知道許多數學上的比較運算子:

- Greater/less than: <code>a &gt; b</code>, <code>a &lt; b</code>.
- Greater/less than or equals: <code>a &gt;= b</code>, <code>a &lt;= b</code>.
- Equals: `a == b` (please note the double equals sign `=`. A single symbol `a = b` would mean an assignment).
- Not equals. In maths the notation is <code>&ne;</code>, but in JavaScript it's written as an assignment with an exclamation sign before it: <code>a != b</code>.
- 大於/小於:<code>a &gt; b</code>, <code>a &lt; b</code>
- 大於等於/小於等於:<code>a &gt;= b</code>, <code>a &lt;= b</code>
- 等於:`a == b`(請注意這裡使用的是兩個等號 `=`。單一個等號 `a = b` 代表的是賦值。
- 不等於:在數學中我們使用 <code>&ne;</code> 來表示,但在 JavaScript 中,是透過在單一個等號前方加上驚嘆號作為表示:<code>a != b</code>

## Boolean is the result
## 比較結果為布林(Boolean)類型

Like all other operators, a comparison returns a value. In this case, the value is a boolean.
如同其他運算子,一個比較運算會回傳一個值。在這個例子中,其回傳值的類型為布林值(Boolean)。

- `true` -- means "yes", "correct" or "the truth".
- `false` -- means "no", "wrong" or "not the truth".
- `true` -- 代表 "yes(是)", "correct(正確)" 或 "the truth(真理)"。
- `false` -- means "no(否)", "wrong(錯誤)" 或 "not the truth(非真理)"。

For example:
範例:

```js run
alert( 2 > 1 ); // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)
alert( 2 > 1 ); // true(正確)
alert( 2 == 1 ); // false(錯誤)
alert( 2 != 1 ); // true(正確)
```

A comparison result can be assigned to a variable, just like any value:
和其他類型的值一樣,比較運算的結果可以被指定給任意變數:

```js run
let result = 5 > 4; // assign the result of the comparison
let result = 5 > 4; // 將比較結果指定給 result 變數
alert( result ); // true
```

## String comparison
## 字串比較

To see whether a string is greater than another, JavaScript uses the so-called "dictionary" or "lexicographical" order.
在比較字串間的大小時,JavaScript 採用所謂 "字典" 或是 "辭典" 順序進行判斷。

In other words, strings are compared letter-by-letter.
換句話說,字串是按照其字母(符)逐個進行比較的。

For example:
範例:

```js run
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
```

The algorithm to compare two strings is simple:
字串比較的演算法很簡單:

1. Compare the first character of both strings.
2. If the first character from the first string is greater (or less) than the other string's, then the first string is greater (or less) than the second. We're done.
3. Otherwise, if both strings' first characters are the same, compare the second characters the same way.
4. Repeat until the end of either string.
5. If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.
1. 比較兩個字串的首位字元大小。
2. 若其中一方的第一個字元大於(或小於)另一個字串的第一個字元,則該字串大於(或小於)另一個字串,演算法結束。
3. 然而,若是兩個字串的首位字元相等,則取出各自的下一位字元,以同樣方法進行比較。
4. 重複上述步驟直到任一字串率先用完所有字元。
5. 如果兩個字串同時比完所有字元,意即擁有相同長度,則可判定雙方為相等。否則,具有尚未比完字元的字串(長度較長)者為大。

In the examples above, the comparison `'Z' > 'A'` gets to a result at the first step while the strings `"Glow"` and `"Glee"` are compared character-by-character:
在上面的範例中,`'Z' > 'A'` 在第一步驟就取得結果,而字串 `"Glow"` `"Glee"` 則繼續按字元逐個比較:

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` `G` 相等。
2. `l` `l` 相等。
3. `o` 大於 `e`,演算法停止,第一個字串較大。

```smart header="Not a real dictionary, but Unicode order"
The comparison algorithm given above is roughly equivalent to the one used in dictionaries or phone books, but it's not exactly the same.
```smart header="並非真正的字典排序,而是 Unicode 順序"
上述的比較演算法跟字典或是電話簿中的排序演算法大致相同,但並非完全ㄧ樣。

For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? The lowercase `"a"`. Why? Because the lowercase character has a greater index in the internal encoding table JavaScript uses (Unicode). We'll get back to specific details and consequences of this in the chapter <info:string>.
譬如大小寫是有差異的,一個大寫的 `"A"` 與小寫的 `"a"` 並不相等。哪一個更大呢?是小寫的 `"a"`。原因在於小寫字符在 JavaScript 使用的內部編碼表中(Unicode)擁有較大的索引值,我們會在 <info:string> 章節中討論更多相關細節。
```

## Comparison of different types
## 不同類型間的比較

When comparing values of different types, JavaScript converts the values to numbers.
當比較不同類型的值時,JavaScript 會先將它們轉換為數值(number)再進行比較。

For example:
範例:

```js run
alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
alert( '2' > 1 ); // true, 字串 '2' 轉換為數值 2
alert( '01' == 1 ); // true, 字串 '01' 轉換為數值 1
```

For boolean values, `true` becomes `1` and `false` becomes `0`.
至於布林值,`true` 變成 `1`,而 `false` 變為 `0`

For example:
範例:

```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="有趣的結果"
有時候,以下狀況會同時發生:

- Two values are equal.
- One of them is `true` as a boolean and the other one is `false` as a boolean.
- 兩者值相同。
- 但若以布林值表示,其中一個是 `true`,另一個則為 `false`

For example:
範例:

```js run
let a = 0;
Expand All @@ -101,109 +101,110 @@ alert( Boolean(b) ); // true
alert(a == b); // true!
```

From JavaScript's standpoint, this result is quite normal. An equality check converts values using the numeric conversion (hence `"0"` becomes `0`), while the explicit `Boolean` conversion uses another set of rules.
JavaScript 的觀點來看,這樣的結果還算正常的。比較運算會將值先轉成數值後才進行比較(因此,`"0"` 變成了 `0`,而明確的 `Boolean` 函式則採用不同的轉換規則。
````

## Strict equality
## 嚴格相等

A regular equality check `==` has a problem. It cannot differentiate `0` from `false`:
普通的相等性檢查 `==` 存在一個問題,它分辨不出 `0` `false` 的差別:

```js run
alert( 0 == false ); // true
```

The same thing happens with an empty string:
同樣無法區別空字串與 `false`:

```js run
alert( '' == false ); // true
```

This happens because operands of different types are converted to numbers by the equality operator `==`. An empty string, just like `false`, becomes a zero.
這是因為不同類型的運算元會被等號運算子 `==` 轉換成數值,空字串與 `false` 都會變成 0。

What to do if we'd like to differentiate `0` from `false`?
如果我們想要區分 `0` `false` 的話該怎麼做呢?

**A strict equality operator `===` checks the equality without type conversion.**
**嚴格相等運算子 `===` 在比較運算時不進行類型轉換。**

In other words, if `a` and `b` are of different types, then `a === b` immediately returns `false` without an attempt to convert them.
換句話說,如果 `a` `b` 屬於不同類型,那 `a === b` 會立即回傳 `false`,並不會執行任何類型轉換。

Let's try it:
讓我們試試:

```js run
alert( 0 === false ); // false, because the types are different
alert( 0 === false ); // false,因為類型不同。
```

There is also a "strict non-equality" operator `!==` analogous to `!=`.
也有與 `!=` 類似的 "嚴格不相等" 運算子 `!==`

The strict equality operator is a bit longer to write, but makes it obvious what's going on and leaves less room for errors.
嚴格相等運算子寫起來有點長,但它很清楚的表示了比較的意圖,並降低出錯的機率。

## Comparison with null and undefined
## 涉及 null undefined 的比較

There's a non-intuitive behavior when `null` or `undefined` are compared to other values.
當使用 `null` `undefined` 與其他值進行比較時,常會出現意料之外的結果。

For a strict equality check `===`
: These values are different, because each of them is a different type.
若以嚴格相等 `===` 做比較
: `null` 與 `undefined` 是不相等的,因為各自屬於不同類型。

```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.
若以非嚴格相等 `==` 做比較
: 存在一個特殊規則是,這兩者被視為一對 "甜蜜情侶":它們彼此相同(在非嚴格相等 `==` 下),但並不相等於其它任何值。

```js run
alert( null == undefined ); // true
```

For maths and other comparisons `< > <= >=`
: `null/undefined` are converted to numbers: `null` becomes `0`, while `undefined` becomes `NaN`.
對於數學式或其他比較方法 `< > <= >=`
: `null/undefined` 會轉換為數值:`null` 變成 `0`,而 `undefined` 變成 `NaN`

Now let's see some funny things that happen when we apply these rules. And, what's more important, how to not fall into a trap with them.
接著讓我們來看看,這些規則會帶來哪些有趣的現象。同時,更重要的是,我們該如何避免掉入這些陷阱。

### Strange result: null vs 0
### 奇怪的結果:null vs 0

Let's compare `null` with a zero:
我們來比較 `null` 與 0:

```js run
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!*
```

Mathematically, that's strange. The last result states that "`null` is greater than or equal to zero", so in one of the comparisons above it must be `true`, but they are both false.
從數學的角度來看,上面的結果很奇怪。最後一行程式碼的執行結果顯示 "`null` 大於等於 0",既然如此,第一與第二行程式碼中,必定有一個的結果為 `true`,然而事實表明其結果皆為 false

The reason is that an equality check `==` and comparisons `> < >= <=` work differently. Comparisons convert `null` to a number, treating it as `0`. That's why (3) `null >= 0` is true and (1) `null > 0` is false.
之所以會出現這個奇怪的結果,是因為相等性檢查 `==` 與比較運算子 `> < >= <=` 的運作邏輯是不同的,比較運算會將 `null` 轉成數值並將其視為 `0`。這就是為何 (3)`null >= 0` 的結果為 true,而(1)`null > 0` false

On the other hand, the equality check `==` for `undefined` and `null` is defined such that, without any conversions, they equal each other and don't equal anything else. That's why (2) `null == 0` is false.
另一方面,`undefined` `null` 在相等性檢查中,被定義為不進行任何類型轉換,且它們除了彼此相等外,不會相等於其他類型的值。這解釋了為什麼(2)`null == 0` 的結果是 false

### An incomparable undefined
### 無法比較的 undefined

The value `undefined` shouldn't be compared to other values:
`undefined` 不應該用來與任何值比較:

```js run
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
```

Why does it dislike zero so much? Always false!
為何它如此討厭 0?總是回傳 false

We get these results because:
原因如下:

- 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`, `undefined`, and no other value.
- 比較式 `(1)`與`(2)`回傳 `false`,因為 `undefined` 在進行比較時,被轉換成了 `NaN`,而 `NaN` 是一個特殊的數字類型,它與任何值比較都會回傳 `false`
- 相等性檢查 `(3)`回傳 `false`,因為在定義中, `undefined` 只與 `null``undefined` 相等,不會與其他值相等。

### Evade problems
### 避免錯誤

Why did we go over 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 problems with them:
為何我們要研究上述範例呢?我們應該要時刻記住這些奇怪的規則嗎?其實並不需要。實際上,隨著時間,你會對這些奇怪的事情漸漸熟悉,但有個更為可靠的方式可以用來避免這方面的問題:

Just treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
除了嚴格相等 `===` 以外,其他凡是有 `undefined/null` 參與的比較運算,多放點心思注意一下。

Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you're really sure of what you're doing. If a variable can have these values, check for them separately.
除非你非常清楚自己在做什麼,否則不要使用 `>= > < <=` 去比較一個可能為 `null/undefined` 的變數。如果一個變數可能會是 `null/undefined`,將這兩者的可能情況分開檢查。

## Summary
## 總結

- 比較運算子總是回傳布林值。
- 字串間的比較是按照 "字典" 順序逐個字符(母)比較。
- 當不同類型的值互相比較時,他們會先被轉換成數值類型(不包含嚴格相等檢查)再進行比較。
- 在非嚴格相等 `==` 下,`null` 與 `undefined` 彼此相等且不等於任何其他值。
- 在使用 `>` 或 `<` 比較時,要小心變數可能為 `null/undefined` 的情況。各別檢查變數是否為 `null/undefined` 會是個好方法。

- Comparison operators return a boolean 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).
- The 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`. Checking for `null/undefined` separately is a good idea.