type coercion ใน Javascript คืออะไร?
ตัวอย่างเช่นในการใช้==แทน===?
type coercion ใน Javascript คืออะไร?
ตัวอย่างเช่นในการใช้==แทน===?
คำตอบ:
Type coercion หมายความว่าเมื่อตัวถูกดำเนินการของตัวดำเนินการเป็นประเภทต่างๆตัวดำเนินการตัวใดตัวหนึ่งจะถูกแปลงเป็นค่า "เทียบเท่า" ของชนิดของตัวถูกดำเนินการอื่น ตัวอย่างเช่นหากคุณทำ:
boolean == integer
ตัวถูกดำเนินการแบบบูลจะถูกแปลงเป็นจำนวนเต็ม: falseกลายเป็น0,trueกลายเป็น 1 จากนั้นทั้งสองค่าจะถูกเปรียบเทียบ
อย่างไรก็ตามหากคุณใช้ตัวดำเนินการเปรียบเทียบที่===ไม่ทำให้เกิด Conversion จะไม่มีการแปลงเกิดขึ้น เมื่อตัวถูกดำเนินการเป็นประเภทที่แตกต่างกันตัวดำเนินการนี้จะส่งคืนfalseและเปรียบเทียบค่าเมื่อเป็นประเภทเดียวกันเท่านั้น
===เมื่อต้องการเปรียบเทียบว่าค่าเท่ากับค่าอื่นหรือไม่?
> , <?
เริ่มต้นด้วยคำแนะนำสั้น ๆ ในการพิมพ์ระบบซึ่งฉันคิดว่าจะช่วยให้คุณเข้าใจแนวคิดทั่วไปของการบังคับประเภท
ระบบประเภทของภาษากำหนดกฎที่บอกเราว่าข้อมูลประเภทใดที่มีอยู่ในภาษานั้นและจะรวมกันได้อย่างไรโดยใช้ตัวดำเนินการที่แตกต่างกัน ตัวอย่างเช่นกฎข้อหนึ่งอาจระบุว่าตัวดำเนินการ plus (+) ทำงานกับตัวเลขเท่านั้น กฎเหล่านี้มีไว้เพื่อป้องกันไม่ให้คุณยิงเท้าตัวเอง แต่จะเกิดอะไรขึ้นเมื่อโปรแกรมเมอร์ฝ่าฝืนกฎนั้นในโปรแกรม? ไม่มีสิ่งใดที่ป้องกันไม่ให้โปรแกรมเมอร์พิมพ์{} + {}หรือ“hello” + 5ในโปรแกรมแม้ว่าภาษาจะไม่คิดว่านิพจน์เหล่านั้นสมเหตุสมผลก็ตาม
สิ่งที่เกิดขึ้นในสถานการณ์เหล่านั้นในท้ายที่สุดขึ้นอยู่กับความเข้มงวดของภาษาเกี่ยวกับกฎประเภท
ระบบประเภทภาษามักมีหนึ่งในสองตำแหน่งเกี่ยวกับการที่คุณละเมิดกฎ:
ภาษาที่มีระบบประเภทที่อยู่ในตำแหน่งแรกเกี่ยวกับกฎนั้นเรียกขานกันว่าภาษา "พิมพ์อย่างรุนแรง" พวกเขาเข้มงวดที่จะไม่ให้คุณทำผิดกฎ ผู้ที่ใช้แนวทางที่สอง (เช่น JavaScript) เรียกว่าภาษา "พิมพ์ผิด" หรือ "พิมพ์ผิด" แน่นอนว่าคุณสามารถฝ่าฝืนกฎได้ แต่อย่าแปลกใจเมื่อมันแปลงประเภทข้อมูลที่คุณอธิบายไว้ในโปรแกรมของคุณโดยการบังคับเพื่อให้เป็นไปตามกฎ พฤติกรรมที่เป็นที่รู้จักกัน ... (ม้วนกลอง) ... ประเภทการบังคับขู่เข็ญ
ตอนนี้เรามาดูตัวอย่างบางส่วนใน JavaScript ก่อนอื่นให้เริ่มต้นด้วยนิพจน์ที่ไม่นำไปสู่การบีบบังคับประเภท
5 + 5
ใช้ตัวดำเนินการ + กับตัวเลขสองตัวซึ่งใช้ได้อย่างสมบูรณ์ โปรแกรมจะถือว่า + หมายถึง "เพิ่ม" และเพิ่มตัวเลขทั้งสองอย่างมีความสุข ไม่จำเป็นต้องแปลง
แต่แล้ว ...
[] + 5
เอ่อโอ้. ใน JavaScript +อาจหมายถึงเพิ่มตัวเลขสองตัวหรือเชื่อมสองสตริงเข้าด้วยกัน ในกรณีนี้เราไม่มีทั้งสองตัวเลขหรือสองสตริง เรามีตัวเลขและวัตถุเพียงตัวเดียว ตามกฎประเภทของ JavaScript สิ่งนี้ไม่สมเหตุสมผล เนื่องจากเป็นเรื่องที่ไม่น่าให้อภัยเกี่ยวกับการที่คุณทำผิดกฎแทนที่จะทำผิดมันก็พยายามทำให้เข้าใจ JavaScript ทำอะไร? มันรู้วิธีการต่อสตริงดังนั้นมันจึงแปลงทั้ง [] และ 5 เป็นสตริงและผลลัพธ์คือค่าสตริง“ 5”
อะไรคือข้อตกลงกับตัวดำเนินการเปรียบเทียบ==และ===? เหตุใดจึงมีตัวดำเนินการเปรียบเทียบสองตัว
==ไม่ได้รับผลกระทบจากพฤติกรรมการแปลงประเภทของ JavaScript นิพจน์เช่น5 == “5”จะประเมินเป็นจริงเนื่องจาก JavaScript จะพยายามแปลงหนึ่งในเพื่อเปรียบเทียบข้อมูลประเภทเดียวกัน
ในหลาย ๆ กรณีไม่เป็นที่พึงปรารถนาเนื่องจากคุณอาจต้องการทราบว่าข้อมูลบางส่วนที่คุณเปรียบเทียบเป็นข้อมูลประเภทอื่นหรือไม่เพื่อที่คุณจะได้ตัดสินใจว่าจะทำอย่างไร นั่นคือสิ่งที่ตัว===ดำเนินการเข้ามาเมื่อคุณใช้จะ===ไม่มีการแปลงประเภทเกิดขึ้น ดังนั้นนิพจน์5 === “5”จะประเมินเป็นเท็จ
ใน Python หากคุณพยายามเพิ่มพูดสตริงและจำนวนเต็มคุณจะได้รับข้อผิดพลาด:
>>> "hi" + 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
แต่ใน JavaScript คุณทำไม่ได้ 10ได้รับการแปลงสตริง:
> "hi" + 10
"hi10"
"การบีบบังคับประเภท" เป็นเพียงการเรียกชื่อที่ไม่ถูกต้องสำหรับข้างต้น ในความเป็นจริงทั้งสองภาษาไม่มี "ประเภท" ในความหมายของ Java หรือ C หรือภาษาอื่น ๆ ที่มีระบบประเภทคงที่ วิธีที่ภาษาใช้ในการโต้ตอบระหว่างค่าต่างๆที่พิมพ์ไม่คงที่เป็นเรื่องของการเลือกและแบบแผน
ให้ฉันอธิบายประเภทการบีบบังคับด้วยตัวอย่างต่อไปนี้
Type Coercion หมายถึง Javascript โดยอัตโนมัติ (on-the-fly) แปลงตัวแปรจากประเภทข้อมูลหนึ่งไปเป็นอีกประเภทหนึ่ง
ตัวอย่าง: 123 + "4"โดยทั่วไปจะทำให้เกิดข้อผิดพลาด แต่ใน Javascript เนื่องจากการบังคับประเภทส่งผล1234ให้เกิดสตริง
if(23 == "23"){
console.log(" this line is inside the loop and is executed ");
}
ในโค้ดข้างต้นเนื่องจากการบังคับประเภท - JavaScript คิดว่า23(ตัวเลข) และ"23"(สตริง) เป็นสิ่งเดียวกัน ทำให้เงื่อนไขเป็นจริงและพิมพ์ console.log
ในอีกกรณีหนึ่ง
if(23 === "23"){
console.log(" this line is inside the loop and is NOT executed");
}
ใน===กรณีที่ Javascript ไม่ได้ทำ Type Coercion และเนื่องจาก23เป็นตัวเลขและ"23"เป็น String และเนื่องจาก===ประเภทข้อมูลทั้งสองนี้แตกต่างกันและนำไปสู่เงื่อนไขที่เป็นเท็จ มันไม่พิมพ์ console.log
พูดง่ายๆ
ในกรณี=นี้เป็นตัวดำเนินการกำหนด - ซึ่งกำหนดค่าเช่นvar a = 3;ฯลฯ
(ด้านล่างตัวดำเนินการสำหรับการเปรียบเทียบ)
ในกรณีนี้==Javascript จะแปลง / บังคับให้ประเภทข้อมูลเป็นประเภทข้อมูลอื่นแล้วเปรียบเทียบ
ในกรณีนี้=== Javascript จะไม่แปลง / บังคับประเภทข้อมูล
เพื่อหลีกเลี่ยงข้อบกพร่องและเพื่อวัตถุประสงค์ในการดีบัก===ส่วนใหญ่จะใช้
โปรดแจ้งให้เราทราบความถูกต้องของข้อมูลข้างต้น
การบังคับประเภทในจาวาสคริปต์เกิดขึ้นเมื่อเอ็นจิน Javascript ต้องดำเนินการบางอย่างซึ่งจำเป็นต้องให้ข้อมูลอยู่ในประเภทหนึ่ง เมื่อเครื่องยนต์พบข้อมูลในบางประเภทที่ไม่สามารถใช้ได้กับการดำเนินการดังกล่าวจะบังคับให้ข้อมูลเป็นประเภทหนึ่ง สิ่งนี้จำเป็นเนื่องจากตัวแปรในจาวาสคริปต์ถูกพิมพ์แบบไดนามิกซึ่งหมายความว่าตัวแปรที่กำหนดสามารถกำหนดค่าประเภทใดก็ได้
if(1){
// 1 gets coerced to true
}
if(4 > '3') {
// 3 gets coerced into a number
}
44 == "44" // true, the string 44 gets converted to a nr
ในการบีบบังคับจาวาสคริปต์ค่าทั้งหมดจะถูกแปลงเป็นtrueยกเว้นค่าต่อไปนี้ซึ่งบังคับให้false:
console.log(!!""); // false
console.log(!!0); // false
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!NaN); // false
console.log(!!false); // false
สังเกตว่าในตัวอย่างข้างต้นว่าคู่! ใช้ตัวดำเนินการ เดอะ! ตัวดำเนินการทำเครื่องหมายบังคับค่าให้เป็นบูลีนด้วยค่าตรงกันข้าม เราสามารถใช้ตัวดำเนินการนี้สองครั้งเพื่อแปลงค่าใด ๆ ให้เป็นบูลีน
a == bวิธีจาวาสคริปต์จะประเมินaกับbบนพื้นฐานถ้าค่าที่สามารถประเมินได้อย่างเท่าเทียมกัน ตัวอย่างเช่นfalse == 0จะประเมินค่าจริงเนื่องจาก 0 เป็นค่าของบูลีนเท็จ อย่างไรก็ตามfalse === 0จะประเมินค่าเท็จเนื่องจากการเปรียบเทียบอย่างเคร่งครัด 0 ไม่ใช่ค่าทางกายภาพเดียวกันกับเท็จ อีกตัวอย่างหนึ่งคือfalse == ''การเปรียบเทียบแบบหลวม ๆ กับการเปรียบเทียบที่เข้มงวดเนื่องจากจาวาสคริปต์เป็นภาษาที่พิมพ์ไม่แน่น กล่าวคือจาวาสคริปต์จะพยายามแปลงตัวแปรตามบริบทของโค้ดและสิ่งนี้มีผลทำให้สิ่งต่าง ๆ เท่าเทียมกันหากไม่มีการเปรียบเทียบอย่างเคร่งครัด php ก็มีพฤติกรรมเช่นนี้เช่นกัน
0 is not the same physical value as false. IMO ร่างกายfalseเป็นสิ่ง0ในหน่วยความจำ ฉันอยากจะบอกว่ามันแตกต่างกันตามประเภทเนื่องจากfalseเป็นบูลีนในขณะที่0เป็นจำนวนเต็ม
Type coercionคือกระบวนการแปลงค่าจากประเภทหนึ่งไปยังอีกประเภทหนึ่ง (เช่นสตริงเป็นตัวเลขอ็อบเจ็กต์เป็นบูลีนและอื่น ๆ ) ประเภทใด ๆ ไม่ว่าจะเป็นแบบดั้งเดิมหรือวัตถุเป็นหัวเรื่องที่ถูกต้องสำหรับการบีบบังคับประเภท ในการเรียกคืน primitives ได้แก่ number, string, boolean, null, undefined + Symbol (เพิ่มใน ES6)
การบังคับขู่เข็ญโดยนัยและชัดแจ้ง อาจเป็นการบังคับอย่างชัดเจนและโดยปริยาย
เมื่อนักพัฒนาแสดงความตั้งใจที่จะแปลงระหว่างประเภทโดยการเขียนโค้ดที่เหมาะสมเช่น Number(value)นี้เรียกว่าการบังคับประเภทอย่างชัดเจน (หรือการคัดเลือกประเภท)
เนื่องจาก JavaScript เป็นภาษาที่พิมพ์ไม่ชัดเจนจึงสามารถแปลงค่าระหว่างประเภทต่างๆได้โดยอัตโนมัติและเรียกว่าการบังคับประเภทโดยนัย มันมักจะเกิดขึ้นเมื่อคุณใช้ผู้ประกอบการค่าของชนิดที่แตกต่างกันเช่น
1 == null, 2/’5', null + new Date()หรือมันสามารถถูกเรียกโดยบริบทโดยรอบเช่นเดียวกับการif (value) {…}ที่ค่าบังคับให้บูล
ตัวดำเนินการหนึ่งที่ไม่ก่อให้เกิดการบีบบังคับประเภทโดยนัยคือ===ซึ่งเรียกว่าตัวดำเนินการความเท่าเทียมกันอย่างเข้มงวด ในทางกลับกันตัวดำเนินการความเท่าเทียมกันแบบหลวม==จะทำการเปรียบเทียบและบังคับประเภทหากจำเป็น
การบีบบังคับประเภทโดยนัยเป็นดาบสองคม: เป็นแหล่งที่มาของความยุ่งยากและข้อบกพร่อง แต่ยังเป็นกลไกที่มีประโยชน์ที่ช่วยให้เราเขียนโค้ดน้อยลงโดยไม่สูญเสียความสามารถในการอ่าน
การแปลงสามประเภท กฎข้อแรกที่ควรทราบคือการแปลงใน JavaScript มีเพียงสามประเภท:
ประการที่สองลอจิกการแปลงสำหรับวัตถุดั้งเดิมและวัตถุทำงานแตกต่างกัน แต่ทั้งดั้งเดิมและวัตถุสามารถแปลงได้ในสามวิธีดังกล่าวเท่านั้น
เริ่มกันที่ไพรเมอร์ก่อน
การแปลงสตริง
ในการแปลงค่าเป็นสตริงอย่างชัดเจนให้ใช้ฟังก์ชัน String () การบังคับโดยนัยถูกเรียกโดยตัวดำเนินการ binary + เมื่อตัวถูกดำเนินการใด ๆ เป็นสตริง:
String(123) // explicit
123 + '' // implicit
ค่าดั้งเดิมทั้งหมดจะถูกแปลงเป็นสตริงตามธรรมชาติอย่างที่คุณคาดหวัง:
String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
การแปลงสัญลักษณ์เป็นเรื่องที่ยุ่งยากเล็กน้อยเนื่องจากสามารถแปลงได้อย่างชัดเจนเท่านั้น แต่ไม่สามารถแปลงโดยปริยายได้
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown
การแปลงบูลีน
หากต้องการแปลงค่าเป็นบูลีนอย่างชัดเจนให้ใช้Boolean()ฟังก์ชัน การแปลงโดยนัยเกิดขึ้นในบริบทเชิงตรรกะหรือถูกทริกเกอร์โดยตัวดำเนินการทางตรรกะ ( || && !)
Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator
หมายเหตุ:ตัวดำเนินการเชิงตรรกะเช่น|| and &&ทำการแปลงบูลีนภายใน แต่ส่งคืนค่าของตัวถูกดำเนินการดั้งเดิมแม้ว่าจะไม่ใช่บูลีนก็ตาม
// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123
ทันทีที่มีผลลัพธ์เพียง 2 ผลลัพธ์ของการแปลงบูลีน: จริงหรือเท็จการจำรายการค่าที่เป็นเท็จก็ทำได้ง่ายขึ้น
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
ค่าใด ๆ ที่ไม่อยู่ในรายชื่อที่จะถูกแปลงเป็นtrueรวมทั้งobject, function, Array, Date, ผู้ใช้กำหนดชนิดและอื่น ๆ สัญลักษณ์เป็นค่าที่แท้จริง อ็อบเจ็กต์และอาร์เรย์ที่ว่างเปล่าเป็นค่าที่แท้จริงเช่นกัน:
Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true
การแปลงตัวเลข
สำหรับการแปลงอย่างชัดเจนเพียงแค่ใช้Number()ฟังก์ชั่นเดียวกับที่คุณทำกับและBoolean()String()
การแปลงโดยนัยเป็นเรื่องยุ่งยากเนื่องจากมีการเรียกใช้ในหลายกรณี:
ตัวดำเนินการเปรียบเทียบ (>, <, <=,> =)
ตัวดำเนินการบิต (| & ^ ~)
ตัวดำเนินการเลขคณิต (- + * /%) โปรดทราบว่าไบนารี + ไม่ทริกเกอร์การแปลงตัวเลขเมื่อตัวถูกดำเนินการใด ๆ เป็นสตริง
ตัวดำเนินการ unary +
ตัวดำเนินการความเสมอภาคหลวม == (รวม! =)
โปรดทราบว่า == ไม่ทริกเกอร์การแปลงตัวเลขเมื่อตัวถูกดำเนินการทั้งสองเป็นสตริง
Number ('123') // Explicit + '123' // implicit 123! = '456' // implicit 4> '5' // implicit 5 / null // implicit true | 0 // นัย
วิธีการแปลงค่าดั้งเดิมเป็นตัวเลขมีดังนี้
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"
ตัวอย่างของตัวแปรที่ประกาศในตอนแรกเป็นสตริงที่ถูกบังคับให้เป็นค่าบูลีนด้วย! ผู้ประกอบการ
Type coercion คือกระบวนการแปลงค่าจากประเภทหนึ่งไปยังอีกประเภทหนึ่ง (เช่นสตริงเป็นตัวเลขอ็อบเจ็กต์เป็นบูลีนและอื่น ๆ ) ประเภทใด ๆ ไม่ว่าจะเป็นแบบดั้งเดิมหรือวัตถุเป็นหัวเรื่องที่ถูกต้องสำหรับการบีบบังคับประเภท ในการเรียกคืน primitives ได้แก่ number, string, boolean, null, undefined + Symbol (เพิ่มใน ES6)
การบีบบังคับประเภทอาจชัดเจนและโดยปริยาย
เมื่อนักพัฒนาแสดงเจตนาที่จะแปลงระหว่างประเภทโดยการเขียนโค้ดที่เหมาะสมเช่น Number (value) จะเรียกว่า Explicit type coercion (หรือ type casting)
เนื่องจาก JavaScript เป็นภาษาที่พิมพ์ไม่ชัดเจนจึงสามารถแปลงค่าระหว่างประเภทต่างๆได้โดยอัตโนมัติและเรียกว่าการบังคับประเภทโดยนัย โดยปกติจะเกิดขึ้นเมื่อคุณใช้ตัวดำเนินการกับค่าประเภทต่างๆเช่น 1 == null, 2 / '5', null + new Date () หรืออาจถูกทริกเกอร์โดยบริบทโดยรอบเช่น if (value) {… } โดยที่ค่าถูกบีบบังคับให้เป็นบูลีน
นี่คือตัวอย่างบางส่วนสำหรับการบีบบังคับประเภทโดยนัย:
true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == ‘x’
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0
อ่านเพิ่มเติม: https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/
หากชนิดข้อมูลไม่เท่ากันการบังคับให้เกิดขึ้น เช่น 3 == "3" หรือ boolen == integer
(true == 1) => true/(true === 1) => false.