JavaScript Wierd Things (Part 2)
เรามาถึง part 2 กันแล้วแต่เราก็ยังไม่พ้นหัวข้อ Type casting เลย 😂ใน part นี้มีข้อมูลที่นำมาจากบล็อกต่างประเทศ ไม่พูดพร้ำทำเพลงเรามาเริ่มกันเลยกับมีมนี้
แต่ถ้าหากคุณไม่เชื่อละก็สามารถพิมพ์ใน console dev tool เพื่อดูผลลัพธ์ได้ จาก part ที่แล้วมาในครั้งนี้ถือว่าไม่น่าแปลกใจเท่าไรแล้ว แต่ก็ยังชวนให้คิดว่า
ทำไมถึงเป็นอย่างนั้นละ?
เพื่อจะอธิบายสิ่งนี้เราจะต้องมาดู official ECMAScript specification ซึ่งเป็นข้อกำหนดของภาษา JS มาดูกันดีกว่า...
ใน Expression แรก 0 == "0"
โดยปกตินั้นการเทียบค่าสองค่าที่มีประเภทที่ต่างกันภาษาโปรแกรมมิ่งเกือบทั้งหมดไม่สามารถทำได้ แต่ในภาษา JS ได้มีการกำหนดส่วนนี้เอาไว้ใน ECMAScript Language Specification ว่า
If x is Number and y is String, return x == ToNumber(y)
เพราะฉนั้นในเคสของ 0 == "0" จะได้ว่า
Since 0 is Number and "0" is String, return 0 == ToNumber("0")
"0" จึงถูกแปลงให้กลายเป็น number ดังนั้นจะกลายเป็น 0 == 0 เพราะฉนั้นเราจึงได้ค่า true นั้นเอง
ใน Expression สอง 0 == []
สิ่งที่เกิดขึ้นนั้นคล้ายกับข้อแรกมากๆ ซึ่งมันก็คือตัวมันนั้นแอบโดนแปลงประเภทอยู่ฉากหลังหากอ้างอิงตาม ECMAScript Language Specification จะได้ว่า
If x is String or Number and y is Object, return x == ToPrimitive(y)
เอ๊? เดียวนะ...
ใช่แล้ว array ใน JS ถือเป็น Object จริงๆแล้วใน JS ตัวแปรทุกประเภทสามารถมีพฤติกรรมเฉกเช่นเดียวกันกับ Object ได้ แต่มันนอกประเด็นเกินไปเราจะพูดถึงเรื่องนี้ใน part ถัดๆไป กลับเข้าสู่เรื่องของเราดีกว่า.. การแปลง array เป็นข้อมูล primitive เราจะได้ข้อมูลประเภทสตริงกลับมาตามข้อกำหนด ซึ่งโดยปกติแล้วข้อมูลที่ได้จะเป็นสมาชิกใน array ที่คั่นด้วยเครื่องหมายจุลภาค ตัวอย่างเช่น
อย่างที่เกริ่นมาว่าข้อมูลที่ได้นั้นจะเป็นสมาชิกใน array เพราะฉนั้นเมื่อเรานำ array เปล่ามาแปลงเราจึงจะได้ string ว่างนั้นเอง (อ้างอิง: https://www.ecma-international.org/ecma-262/5.1/#sec-9.1 และ https://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8)
จากที่ว่ามาตอนนี้ array ได้กลายเป็น "" เราจึงจะได้ว่า 0 == "" ซึ่งเราก็จะวนกลับเขา algorithm แรก
If x is Number and y is String, return x == ToNumber(y)
เพราะฉนั้นในเคสของ 0 == "" จะได้ว่า
Since 0 is Number and "" is String, return 0 == ToNumber("")
แต่การแปลงสตริงว่างเป็น number เราจะได้ 0
เพราะฉนั้น 0 == 0 อีกแล้ว...
มาทวนกันอีกครั้ง
0 == "0" เป็นจริง
เพราะมันถุกบังครับให้กลายเป็น 0 == ToNumber("0")
และ
0 == [] เป็นจริง
เพราะมันถูกแปลงสองครั้ง:
ในครั้งแรก ToPrimitive([]) ให้ผลลัพธ์ "" จึงนำพามาซึ่งครั้งที่สองคือ ToNumber("") ให้ผลลัพธ์ 0
"0" == [] เป็นเท็จ!
ถูกต้อง! ถ้าหากเข้าใจการทำงานแล้วนี่เป็นสิ่งที่ make sense แต่ถ้าคุณไม่เข้าใจผมจะอธิบายให้ฟัง
อย่างอิง ECMAScript Language Specification อีกครั้ง
If x is String or Number and y is Object, return x == ToPrimitive(y)
นั้นหมายความว่า...
Since "0" is String and [] is Object, return x == ToPrimitive([])
ToPrimitive([]) เราจะได้ "" เพราะฉนั้นตอนนี้การเปรียบเทียบเราจะได้
"0" == ""
"0" และ "" ทั้งคู่เป็น string เพราะฉนั้น JS Engine จึงไม่จำเป็นต้องแปลงอีกคำตอบออกมาจึงเป็น false
เอาละครับสุดท้ายนี้ขอลาไปกับมีมตลกๆ ละกันครับ ขอบคุณครับ




ความคิดเห็น
แสดงความคิดเห็น