[05] JavaScript 入門 - 相等性、不等性


keywords: equality,inequality,charCodeAt,fromCharCode,ECMAScript-11.8.1、11.8.5

相等性 ( Equality )

JavaScript 有四種相等性運算子 ==、===、!==、!===

  • == 檢查值的相等性,並允許強制轉型
  • === 檢查值的相等性,但不允許強制轉型,又稱為嚴格相等性( strict equality )

如果比較的是非基型值,像是 object ( 包含 function、array ),在進行 ===== 的比較時,實際上是藉由參考 ( by reference ) ,意思是只會檢查參考的地方是否相等,不會檢查底層所含的那些值
ex:

let x =[4,5,6]
let y =[4,5,6]
let z ="4,5,6"

x == z // true   [4,5,6].toString() // "4,5,6"
y == z // true
x == y // false   只檢查參考,不會檢查值

不等性 ( Inequality )

不等性 <、>、<=、>= 通常被用在能夠比較順序的值,像是 number ,不過 string 也可以比較不等性,使用的是字母順序規則。

  1. 根據 ECMAScript 11.8.5 第三點 如果兩個 case 不是均為 string,兩個值皆會被強制轉型為 number 後再做比較:

    If it is not the case that both Type(px) is String and Type(py) is String,
    a. Let nx be the result of calling ToNumber(px).
    b. Let ny be the result of calling ToNumber(py).

  2. 兩邊皆 string 比較字母順序,根據 ECMAScript 11.8.5 的 第四點及 NOTE2:

    The comparison of Strings uses a simple lexicographic ordering on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore String values that are canonically equal according to the Unicode standard could test as unequal.

    2-1. 字串的比較使用簡單的字典順序來排序,也就是英文字典的順序 aa > ab > ac > ba
    2-2. 如果是大小寫的字串比較呢? 則使用 Unicode standard 規範來做比較

    先來看看例子:

    • 根據字典順序:
      'a' > 'b' // false  ∵ b 排在 a 後面 ∴ false
      'ab' > 'aa' // true
      'ab' > 'ac' // false
      'za' > 'ba' // true
      
    • 大小寫字母比較,使用 Unicode standard,可以使用 String.charCodeAt(index?) 查詢 UTF-16 code

      1. 不同大小字母
        'a' > 'A' // true  a:97  A:65
        'a'.charCodeAt() // 97
        'A'.charCodeAt() // 65
        
      2. 🚩 一次只能回傳一個字母的 UTF-16 code 如果輸入一個字元以上,記得傳入 index,如果沒輸入就預設 0
        'ab'.charCodeAt() // 97
        'ab'.charCodeAt(1) // 98
        'ab' > 'aC' // true b:98 C:67
        
      3. 😏 有趣的例子:

        • 當比對的字串字數不一致時會怎麼樣?

          'z' > 'za' // false
          'z' > 'aa' // true
          
          雖然知道根據說明是使用字典順序規則,但還是想試試會不會是以數字加總比大小 XD 
          
          結果 z // 122   aa // 194 (97*2) 果然是以字典順序
          
          如果沒記錯以前在翻字典的時候,每一個字母的第一個一定是自己本身 ex: a
          
          所以 z 會在 za 前面故 'z' > 'za' 為 false
          
        • 當看似非字串實際上是字串與字串比對時呢?

          '99' > 'a' // false
          '99'.charCodeAt() // 57  
          
          🚩注意 '9' 的 Unicode 是 57,因為編碼只有編 0~9 ∴ 實際上是 '9' > 'a' 做比較
          
          '我' > 'a' // true
          '我'.charCodeAt() // 25105
          
          'a9' > 'a' // true 
          
          這邊要用 Unicode + 字典順序的排序去看。
          就像 'z' > 'za' 發現第一個一樣,因此按照第二個去排
          所以這邊第一個 a 一樣所以比第二個發現  9VS無 ,故 'a9' > 'a'
          
          '9a' > 'a' // false
          
          這裡比的是第一個 '9' > 'a' 由上方得知 '9' 的 Unicode 是 57 
          57 > 97 故 false
          

          補充:相反地可以使用 String.fromCharCode() 來反查數字代表的是什麼,這個就沒有只能查一個的規定了

          String.fromCharCode(97) // "a"
          String.fromCharCode(97,65) // "aA"
          
  3. 有可能會發生的最大意外是其中一個值無法被轉為有效的數字
    先看例子:

    42 < 'a' // false
    42 > 'a' // false
    42 == 'a' // false   what!? 😱
    

    我們知道 'a' 的 Unicode 是 97 應該會大於 42 勒🤔
    這邊有幾個 Tips:

    • 只有當兩邊均為 string 才會使用 Unicode 去做字典順序的比較
    • 如果一方是 number 就會進行非數字的 ToNumber 強制轉型

      比較時根據 ECMAScript 11.8.1

      5.Let r be the result of performing abstract relational comparison lval rval. (see 11.8.5)
      6.If r is undefined, return false. Otherwise, return r.

      ECMAScript 11.8.5

      第三點的 c.If nx is NaN, return undefined.

      整理一下:
      1.如果一方為數字,另外一方非數字的就進行 ToNumber 的強制轉型,但是 Number('a') // NaN 稱為無效數字值,根據 11.8.5 如果轉型後是 NaN 回傳 undefined
      2.接到 11.8.1 後,第六點說如果接到 undefined 回傳 false

      NaN === NaN // false  NaN 是整個語言中唯一不等於自己的值 O.o
      Number('{}') // NaN
      Number('[]') // NaN
      

小結 ( 按照順序 ):

  1. 比較時,雙方為數字,就進行數字的比較
  2. 比較時,一方為數字,一方為非數字,非數字進行 ToNumber Coercion
    2-1. 如果 Number() 回傳 NaN return undefined
    2-2. 比較運算子接到 undefined 後 return false
  3. 比較時,雙方都是 string 就進行字母順序比較,如果遇到大小寫則使用 Unicode 做比較 ( 雙方在都是小寫時也適用 Unicode 做比較)
#equality #inequality #String.fromCharCode() #String.charCodeAt() #ECMAScript-11.8.1 #ECMAScript-11.8.5







你可能感興趣的文章

Express template engine - Handlebars 載入 使用

Express template engine - Handlebars 載入 使用

Decoding A/B Testing: The Magic of the Paired T-Test

Decoding A/B Testing: The Magic of the Paired T-Test

[JS] 參數傳遞方式 Call by what?

[JS] 參數傳遞方式 Call by what?






留言討論