ความแตกต่างระหว่าง==
และ===
คืออะไร?
- การ
==
เปรียบเทียบแบบหลวม ๆทำงานอย่างไร - การ
===
เปรียบเทียบที่เข้มงวดทำงานอย่างไร
อะไรคือตัวอย่างที่มีประโยชน์
ความแตกต่างระหว่าง==
และ===
คืออะไร?
==
เปรียบเทียบแบบหลวม ๆทำงานอย่างไร===
เปรียบเทียบที่เข้มงวดทำงานอย่างไรอะไรคือตัวอย่างที่มีประโยชน์
คำตอบ:
==
และ===
ความแตกต่างระหว่าง==
โอเปอเรเตอร์ที่เท่ากันอย่างหลวมและโอเปอเรเตอร์ที่===
เหมือนกันอย่างเข้มงวดถูกอธิบายไว้ในคู่มือ :
ผู้ประกอบการเปรียบเทียบ
┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐ │ตัวอย่าง│ชื่อ│ผลลัพธ์│ ├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤ │ $ a == $ b │เท่ากับ│ TRUE หาก $ a เท่ากับ $ b หลังจากเล่นกลแบบ │ │ $ a === $ b │เหมือนกัน│ TRUE ถ้า $ a เท่ากับ $ b และเป็นประเภทเดียวกัน │ └──────────┴───────────┴────────────────────────── ─────────────────────────────────┘
==
เปรียบเทียบกันอย่างหลวม ๆหากคุณกำลังใช้==
ประกอบการหรือดำเนินการเปรียบเทียบอื่น ๆ ซึ่งใช้กันอย่างหลวม ๆ เปรียบเทียบเช่น!=
, <>
หรือ==
คุณมักจะมีไปดูที่บริบทที่จะเห็นสิ่งที่และทำไมบางสิ่งบางอย่างได้รับการแปลงที่จะเข้าใจสิ่งที่เกิดขึ้น
เป็นข้อมูลอ้างอิงและตัวอย่างคุณสามารถดูตารางเปรียบเทียบในคู่มือ :
เปรียบเทียบกับ
==
┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐ ││ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "0" -1 "│อาร์เรย์ NULL │ () ph" php "│" "│ ├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤ │ TRUE │ TRUE │ FALSE │ TRUE AL FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ AL FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ │ 1 │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 0 │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ │ -1 │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "1" │ TRUE │ FALSE │ TRUE AL FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "0" AL FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "-1" │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ ULL NULL │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ │ array () │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRAL │ FALSE │ FALSE │ │ "php" │ TRUE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE AL FALSE │ FALSE │ TRUE │ └─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘
===
การเปรียบเทียบที่เหมือนกันอย่างเข้มงวดหากคุณกำลังใช้===
โอเปอเรเตอร์หรือโอเปอเรเตอร์การเปรียบเทียบอื่น ๆ ที่ใช้การเปรียบเทียบอย่างเข้มงวดเช่น!==
หรือ===
จากนั้นคุณสามารถมั่นใจได้ว่าประเภทจะไม่เปลี่ยนแปลงอย่างน่าอัศจรรย์เพราะจะไม่มีการแปลงเกิดขึ้น ดังนั้นด้วยการเปรียบเทียบอย่างเข้มงวดชนิดและค่าจะต้องเหมือนกันไม่ใช่เฉพาะค่า
เป็นข้อมูลอ้างอิงและตัวอย่างคุณสามารถดูตารางเปรียบเทียบในคู่มือ :
การเปรียบเทียบที่เข้มงวดกับ
===
┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐ ││ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "0" -1 "│อาร์เรย์ NULL │ () ph" php "│" "│ ├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤ │ TRUE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ AL FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 1 │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ 0 │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ -1 │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "1" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "0" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ │ "-1" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ ULL NULL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ │ array () │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ ph "php" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │ │ "" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │ └─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘
true
false
มันง่ายที่จะร่าย แม้ว่าจะมีค่าอื่น ๆ ทั้งหมดสำหรับการใช้งานจริงทั้งหมดรวมกันได้ไม่ จำกัด คือ"five" == 5
อะไร array(0) == 0
? array(0,0,0) == 0
? 0.0000000000000000000000000000000000000000000000000001 == array()
?
false
สำหรับอาร์เรย์ที่แตกต่างกันใน JavaScript แต่true
สำหรับ PHP ตราบใดที่ค่าของพวกเขามีความเท่าเทียมกัน
"000" != "00"
, "000" == null
, "000" == false
, "0x0" == false
, array() == 0
, false != null
, array() != null
, ,false == "0x0"
ใน PHP มันเป็นพฤติกรรมที่ตรงข้าม: , , , , , , , , false == "000"
"000" == "00"
"000" != null
"000" != false
"0x0" != false
array() != 0
false == null
array() == null
false != "0x0"
false != "000"
ผู้ประกอบการ == ปลดเปลื้องระหว่างสองประเภทที่แตกต่างกันหากพวกเขาจะแตกต่างกันในขณะที่ผู้ประกอบการ === ดำเนินการ 'การเปรียบเทียบ typesafe' นั่นหมายความว่ามันจะคืนค่าจริงถ้าตัวถูกดำเนินการทั้งสองมีประเภทเดียวกันและมีค่าเท่ากัน
ตัวอย่าง:
1 === 1: true
1 == 1: true
1 === "1": false // 1 is an integer, "1" is a string
1 == "1": true // "1" gets casted to an integer, which is 1
"foo" === "foo": true // both operands are strings and have the same value
คำเตือน : สองอินสแตนซ์ของคลาสเดียวกันกับสมาชิกที่เทียบเท่าไม่ตรงกับ===
โอเปอเรเตอร์ ตัวอย่าง:
$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
ภาพที่มีค่าพันคำ:
==
เท่าเทียมกันแผนภูมิ:===
chart:ซอร์สโค้ดเพื่อสร้างภาพเหล่านี้:
https://github.com/sentientmachine/php_equality_charts
ผู้ที่ต้องการรักษาสติไม่อ่านเพิ่มเติมเพราะไม่มีสิ่งนี้จะทำให้รู้สึกใด ๆ ยกเว้นที่จะบอกว่านี่เป็นวิธีที่ PHP เศษเล็กเศษน้อยที่ได้รับการออกแบบ
NAN != NAN
แต่ NAN == true
แต่ ==
จะแปลงตัวถูกดำเนินการซ้ายและขวาให้เป็นตัวเลขหากเหลือเป็นตัวเลข ดังนั้น123 == "123foo"
แต่"123" != "123foo"
สตริงเลขฐานสิบหกในเครื่องหมายคำพูดเป็นลอยในบางครั้งและจะถูกโยนแปลกใจที่จะลอยกับความประสงค์ของคุณทำให้เกิดข้อผิดพลาดรันไทม์
==
ไม่ได้เพราะสกรรมกริยา"0"== 0
และ0 == ""
แต่"0" != ""
==
มีวิธีที่จะเป็นตัวแทนของตัวแปรที่ไม่ได้กำหนดเป็นคุณลักษณะที่ถูกปิดใช้งานด้วย"6" == " 6"
, "4.2" == "4.20"
และแต่"133" == "0133"
133 != 0133
แต่"0x10" == "16"
และ"1e3" == "1000"
การเปิดเผยว่าการแปลงสตริงของเซอร์ไพรส์เป็นฐานแปดจะเกิดขึ้นทั้งคู่โดยที่คุณไม่ได้รับคำแนะนำหรือยินยอมทำให้เกิดข้อผิดพลาดรันไทม์
False == 0
, ""
, []
และ"0"
และ
เมื่อตัวเลขมีขนาดใหญ่พอจะมีค่าเป็น == Infinity
คลาสใหม่คือ == ถึง 1
หากคุณใช้ PHP คุณจะไม่ใช้ตัวดำเนินการเท่ากับสองเท่าเพราะถ้าคุณใช้สามเท่ากับกรณีขอบเดียวที่ต้องกังวลคือ NAN และตัวเลขใกล้เคียงกับอนันต์ที่พวกเขาจะไม่มีที่สิ้นสุด ด้วยการเท่ากับสองเท่าสิ่งใดก็ตามที่สามารถสร้างความประหลาดใจ==
ให้กับทุกสิ่งหรือหรือสามารถสร้างความประหลาดใจเมื่อเทียบกับความต้องการของคุณและ!=
สิ่งที่ควรจะเท่ากันอย่างเห็นได้ชัด
ทุกที่ที่คุณใช้==
ใน PHP นั้นเป็นโค้ดที่ไม่ดีเพราะมีบั๊ก 85 ตัวที่ถูกเปิดเผยโดยกฎการส่งข้อมูลโดยปริยาย
เกี่ยวกับ JavaScript:
ตัวดำเนินการ === ทำงานเหมือนกับตัวดำเนินการ == แต่ต้องการให้ตัวถูกดำเนินการนั้นไม่เพียง แต่มีค่าเท่ากัน แต่ยังเป็นชนิดข้อมูลเดียวกัน
ตัวอย่างเช่นตัวอย่างด้านล่างจะแสดง 'x และ y เท่ากัน' แต่ไม่ใช่ 'x และ y เท่ากัน'
var x = 4;
var y = '4';
if (x == y) {
alert('x and y are equal');
}
if (x === y) {
alert('x and y are identical');
}
นอกเหนือจากคำตอบอื่น ๆ ที่เกี่ยวข้องกับการเปรียบเทียบวัตถุ:
== เปรียบเทียบวัตถุโดยใช้ชื่อของวัตถุและค่าของพวกเขา หากวัตถุสองชนิดเป็นชนิดเดียวกันและมีค่าสมาชิกเหมือนกัน$a == $b
จะให้ผลเป็นจริง
=== เปรียบเทียบ id วัตถุภายในของวัตถุ แม้ว่าสมาชิกจะเท่ากัน$a !== $b
ถ้าพวกเขาไม่ใช่วัตถุเดียวกัน
class TestClassA {
public $a;
}
class TestClassB {
public $a;
}
$a1 = new TestClassA();
$a2 = new TestClassA();
$b = new TestClassB();
$a1->a = 10;
$a2->a = 10;
$b->a = 10;
$a1 == $a1;
$a1 == $a2; // Same members
$a1 != $b; // Different classes
$a1 === $a1;
$a1 !== $a2; // Not the same object
ในแง่ง่ายที่สุด:
== ตรวจสอบว่าเทียบเท่า (ค่าเท่านั้น)
=== ตรวจสอบว่าเหมือนกัน (ค่า && ประเภท)
เทียบเท่ากับเดียวกัน: การเปรียบเทียบ
1 + 1 = 2 + 0 (เทียบเท่า)
1 + 1 = 1 + 1 (เหมือนกัน)
ใน PHP:
true == 1 (จริง - เทียบเท่ามูลค่า)
true === 1 (เท็จ - ไม่เหมือนกันในค่า && ประเภท)
มันคือทั้งหมดที่เกี่ยวกับประเภทข้อมูล ยกตัวอย่างBOOL
(จริงหรือเท็จ):
true
ยังเท่ากับ1
และ
false
เท่ากับ0
==
ไม่สนใจเกี่ยวกับชนิดข้อมูลเมื่อเปรียบเทียบ: ดังนั้นถ้าคุณมีตัวแปรที่ 1 (ซึ่งอาจจะเป็นtrue
):
$var=1;
แล้วเปรียบเทียบกับ==
:
if ($var == true)
{
echo"var is true";
}
แต่$var
ไม่เท่ากันจริงtrue
เหรอ? มันมีค่า int 1
แทนซึ่งจะเท่ากับจริง
ด้วย===
ชนิดข้อมูลจะถูกตรวจสอบเพื่อให้แน่ใจว่าทั้งสองตัวแปร / วัตถุ / สิ่งที่ใช้ชนิดเดียวกัน
ดังนั้นถ้าฉันทำ
if ($var === true)
{
echo "var is true";
}
เงื่อนไขนั้นจะไม่เป็นจริงตาม$var !== true
นั้นเท่านั้น== true
(ถ้าคุณรู้ว่าฉันหมายถึงอะไร)
ทำไมคุณต้องการสิ่งนี้
ง่าย - ลองมาดูหนึ่งในฟังก์ชั่นของ PHP array_search()
:
array_search()
ฟังก์ชั่นการค้นหาเพียงสำหรับค่าในอาร์เรย์และผลตอบแทนที่สำคัญขององค์ประกอบค่าที่ถูกพบใน. ถ้าค่าไม่พบในอาร์เรย์ก็จะส่งกลับเท็จ แต่ถ้าคุณทำarray_search()
ตามค่าที่เก็บไว้ในองค์ประกอบแรกของอาร์เรย์ (ซึ่งจะมีคีย์อาร์เรย์ของ0
) ....array_search()
ฟังก์ชั่นจะกลับ 0 ... ซึ่งเท่ากับเท็จ ..
ดังนั้นถ้าคุณทำ:
$arr = array("name");
if (array_search("name", $arr) == false)
{
// This would return 0 (the key of the element the val was found
// in), but because we're using ==, we'll think the function
// actually returned false...when it didn't.
}
ดังนั้นคุณเห็นว่าสิ่งนี้อาจเป็นปัญหาได้หรือไม่
คนส่วนใหญ่ไม่ใช้== false
เมื่อตรวจสอบว่าฟังก์ชันส่งกลับค่าเท็จหรือไม่ !
แต่พวกเขาใช้ แต่จริงๆแล้วมันเหมือนกับการใช้==false
ดังนั้นถ้าคุณทำ:
$arr = array("name");
if (!array_search("name", $arr)) // This is the same as doing (array_search("name", $arr) == false)
ดังนั้นสำหรับสิ่งต่าง ๆ เช่นนั้นคุณจะใช้===
แทนเพื่อให้มีการตรวจสอบชนิดข้อมูล
ตัวอย่างหนึ่งคือแอ็ตทริบิวต์ฐานข้อมูลอาจเป็นโมฆะหรือ "":
$attributeFromArray = "";
if ($attributeFromArray == ""){} //true
if ($attributeFromArray === ""){} //true
if ($attributeFromArray == null){} //true
if ($attributeFromArray === null){} //false
$attributeFromArray = null;
if ($attributeFromArray == ""){} //true
if ($attributeFromArray === ""){} //false
if ($attributeFromArray == null){} //true
if ($attributeFromArray === null){} //true
php == เป็นตัวดำเนินการเปรียบเทียบซึ่งเปรียบเทียบค่าของตัวแปร แต่ === เปรียบเทียบค่าและชนิดข้อมูล
ตัวอย่างเช่น,
<?php
$var1 = 10;
$var2 = '10';
if($var1 == $var2) {
echo 'Variables are equal';
} else {
echo 'Variables are not equal';
}
?>
ในกรณีนี้ผลลัพธ์จะเป็น 'ตัวแปรเท่ากัน' แม้ว่าประเภทข้อมูลจะแตกต่างกัน
แต่ถ้าเราใช้ === แทนที่จะเป็น == ผลลัพธ์จะเป็น 'ตัวแปรไม่เท่ากัน' php ก่อนจะเปรียบเทียบค่าของตัวแปรจากนั้นชนิดข้อมูล ที่นี่ค่าเหมือนกัน แต่ชนิดข้อมูลแตกต่างกัน
ป.ร. ให้ไว้ x = 5
1) ผู้ประกอบการ: == คือ "เท่ากับ" x == 8
เป็นเท็จ
2) ผู้ประกอบการ: === คือ "เท่ากับเท่ากับ" (ค่าและประเภท) x === 5
เป็นจริงx === "5"
เป็นเท็จ
$a = 5; // 5 as an integer
var_dump($a == 5); // compare value; return true
var_dump($a == '5'); // compare value (ignore type); return true
var_dump($a === 5); // compare type/value (integer vs. integer); return true
var_dump($a === '5'); // compare type/value (integer vs. string); return false
ระวังให้ดี นี่คือปัญหาที่มีชื่อเสียง
// 'test' is found at position 0, which is interpreted as the boolean 'false'
if (strpos('testing', 'test')) {
// code...
}
เมื่อเทียบกับ
// true, as strict comparison was made (0 !== false)
if (strpos('testing', 'test') !== false) {
// code...
}
ในระยะสั้น === ทำงานในลักษณะเดียวกับที่ == ทำในภาษาการเขียนโปรแกรมอื่นส่วนใหญ่
PHP ช่วยให้คุณทำการเปรียบเทียบที่ไม่สมเหตุสมผล ตัวอย่าง:
$y = "wauv";
$x = false;
if ($x == $y)
...
ขณะที่สิ่งนี้อนุญาตให้ "ทางลัด" ที่น่าสนใจบางอย่างคุณควรระวังเนื่องจากฟังก์ชั่นที่คืนสิ่งที่ไม่ควร (เช่น "ข้อผิดพลาด" แทนที่จะเป็นตัวเลข) จะไม่ถูกจับได้และคุณจะสงสัยว่าเกิดอะไรขึ้น
ใน PHP == เปรียบเทียบค่าและทำการแปลงประเภทหากจำเป็น (ตัวอย่างเช่นสตริง "12343sdfjskfjds" จะกลายเป็น "12343" ในการเปรียบเทียบจำนวนเต็ม) === จะเปรียบเทียบค่าและชนิดและจะส่งคืนค่าเท็จหากชนิดไม่เหมือนกัน
หากคุณดูในคู่มือ PHP คุณจะเห็นว่าฟังก์ชันจำนวนมากส่งคืน "false" หากฟังก์ชันล้มเหลว แต่อาจส่งคืน 0 ในสถานการณ์ที่ประสบความสำเร็จซึ่งเป็นสาเหตุที่พวกเขาแนะนำให้ทำ "if (function ()! == false) "เพื่อหลีกเลี่ยงข้อผิดพลาด
ไม่กี่ตัวอย่าง
var_dump(5 == 5); // True
var_dump(5 == "5"); // True because == checks only same value not type
var_dump(5 === 5); // True
var_dump(5 === "5"); // False because value are same but data type are different.
PS
== เปรียบเทียบค่าเท่านั้นมันจะไม่รบกวนเกี่ยวกับประเภทข้อมูล
เมื่อเทียบกับ
=== เปรียบเทียบค่าและชนิดข้อมูล
คุณจะใช้ === เพื่อทดสอบว่าฟังก์ชั่นหรือตัวแปรเป็นเท็จมากกว่าเพียงแค่เท่ากับเป็นเท็จ (ศูนย์หรือสตริงว่าง)
$needle = 'a';
$haystack = 'abc';
$pos = strpos($haystack, $needle);
if ($pos === false) {
echo $needle . ' was not found in ' . $haystack;
} else {
echo $needle . ' was found in ' . $haystack . ' at location ' . $pos;
}
ในกรณีนี้ strpos จะคืนค่า 0 ซึ่งจะถือว่าเป็นเท็จในการทดสอบ
if ($pos == false)
หรือ
if (!$pos)
ซึ่งไม่ใช่สิ่งที่คุณต้องการที่นี่
สำหรับเมื่อจะใช้อย่างใดอย่างหนึ่งใช้ตัวอย่างfwrite()
ฟังก์ชั่นใน PHP
ฟังก์ชั่นนี้เขียนเนื้อหาไปยังสตรีมไฟล์ ตาม PHP, " fwrite()
ส่งคืนจำนวนไบต์ที่เขียน, หรือ FALSE เนื่องจากข้อผิดพลาด" หากคุณต้องการทดสอบว่าการเรียกใช้ฟังก์ชันสำเร็จหรือไม่วิธีนี้จะมีข้อบกพร่อง:
if (!fwrite(stuff))
{
log('error!');
}
มันสามารถกลับเป็นศูนย์ (และถือว่าประสบความสำเร็จ) และสภาพของคุณยังคงได้รับการเรียก วิธีที่ถูกต้องคือ:
if (fwrite(stuff) === FALSE)
{
log('error!');
}
PHP เป็นภาษาที่พิมพ์อย่างหลวม ๆ การใช้ตัวดำเนินการเท่ากันสองเท่าช่วยให้สามารถตรวจสอบตัวแปรได้อย่างหลวม ๆ
การตรวจสอบค่าที่หลวมจะช่วยให้ค่าที่คล้ายกัน แต่ไม่เท่ากันมีค่าเท่ากัน:
ค่าเหล่านี้ทั้งหมดจะเท่ากันโดยใช้ตัวดำเนินการเท่ากับสองเท่า
ตัวแปรมีชนิดและค่า
เมื่อคุณใช้ตัวแปรเหล่านี้ (เป็น PHP) บางครั้งคุณอาจมีประเภทที่ไม่ดี ตัวอย่างเช่นถ้าคุณทำ
if ($var == 1) {... do something ...}
PHP ต้องแปลง ("to cast") $ var เป็นจำนวนเต็ม ในกรณีนี้ "$ var == 1" เป็นจริงเพราะสตริงที่ไม่ว่างจะถูกส่งไปที่ 1
เมื่อใช้ === คุณตรวจสอบว่าค่าและประเภทเท่ากันดังนั้น "$ var === 1" จึงเป็นเท็จ
สิ่งนี้มีประโยชน์ตัวอย่างเช่นเมื่อคุณมีฟังก์ชั่นที่สามารถคืนค่าเท็จ (เมื่อเกิดข้อผิดพลาด) และ 0 (ผลลัพธ์):
if(myFunction() == false) { ... error on myFunction ... }
รหัสนี้ผิดเหมือนmyFunction()
คืน 0 มันถูกโยนเป็นเท็จและคุณดูเหมือนจะมีข้อผิดพลาด รหัสที่ถูกต้องคือ:
if(myFunction() === false) { ... error on myFunction ... }
เพราะการทดสอบคือค่าตอบแทน "เป็นบูลีนและเป็นเท็จ" และไม่ใช่ "สามารถแปลงเป็นเท็จ"
<?php
/**
* Comparison of two PHP objects == ===
* Checks for
* 1. References yes yes
* 2. Instances with matching attributes and its values yes no
* 3. Instances with different attributes yes no
**/
// There is no need to worry about comparing visibility of property or
// method, because it will be the same whenever an object instance is
// created, however visibility of an object can be modified during run
// time using ReflectionClass()
// http://php.net/manual/en/reflectionproperty.setaccessible.php
//
class Foo
{
public $foobar = 1;
public function createNewProperty($name, $value)
{
$this->{$name} = $value;
}
}
class Bar
{
}
// 1. Object handles or references
// Is an object a reference to itself or a clone or totally a different object?
//
// == true Name of two objects are same, for example, Foo() and Foo()
// == false Name of two objects are different, for example, Foo() and Bar()
// === true ID of two objects are same, for example, 1 and 1
// === false ID of two objects are different, for example, 1 and 2
echo "1. Object handles or references (both == and ===) <br />";
$bar = new Foo(); // New object Foo() created
$bar2 = new Foo(); // New object Foo() created
$baz = clone $bar; // Object Foo() cloned
$qux = $bar; // Object Foo() referenced
$norf = new Bar(); // New object Bar() created
echo "bar";
var_dump($bar);
echo "baz";
var_dump($baz);
echo "qux";
var_dump($qux);
echo "bar2";
var_dump($bar2);
echo "norf";
var_dump($norf);
// Clone: == true and === false
echo '$bar == $bar2';
var_dump($bar == $bar2); // true
echo '$bar === $bar2';
var_dump($bar === $bar2); // false
echo '$bar == $baz';
var_dump($bar == $baz); // true
echo '$bar === $baz';
var_dump($bar === $baz); // false
// Object reference: == true and === true
echo '$bar == $qux';
var_dump($bar == $qux); // true
echo '$bar === $qux';
var_dump($bar === $qux); // true
// Two different objects: == false and === false
echo '$bar == $norf';
var_dump($bar == $norf); // false
echo '$bar === $norf';
var_dump($bar === $norf); // false
// 2. Instances with matching attributes and its values (only ==).
// What happens when objects (even in cloned object) have same
// attributes but varying values?
// $foobar value is different
echo "2. Instances with matching attributes and its values (only ==) <br />";
$baz->foobar = 2;
echo '$foobar' . " value is different <br />";
echo '$bar->foobar = ' . $bar->foobar . "<br />";
echo '$baz->foobar = ' . $baz->foobar . "<br />";
echo '$bar == $baz';
var_dump($bar == $baz); // false
// $foobar's value is the same again
$baz->foobar = 1;
echo '$foobar' . " value is the same again <br />";
echo '$bar->foobar is ' . $bar->foobar . "<br />";
echo '$baz->foobar is ' . $baz->foobar . "<br />";
echo '$bar == $baz';
var_dump($bar == $baz); // true
// Changing values of properties in $qux object will change the property
// value of $bar and evaluates true always, because $qux = &$bar.
$qux->foobar = 2;
echo '$foobar value of both $qux and $bar is 2, because $qux = &$bar' . "<br />";
echo '$qux->foobar is ' . $qux->foobar . "<br />";
echo '$bar->foobar is ' . $bar->foobar . "<br />";
echo '$bar == $qux';
var_dump($bar == $qux); // true
// 3. Instances with different attributes (only ==)
// What happens when objects have different attributes even though
// one of the attributes has same value?
echo "3. Instances with different attributes (only ==) <br />";
// Dynamically create a property with the name in $name and value
// in $value for baz object
$name = 'newproperty';
$value = null;
$baz->createNewProperty($name, $value);
echo '$baz->newproperty is ' . $baz->{$name};
var_dump($baz);
$baz->foobar = 2;
echo '$foobar' . " value is same again <br />";
echo '$bar->foobar is ' . $bar->foobar . "<br />";
echo '$baz->foobar is ' . $baz->foobar . "<br />";
echo '$bar == $baz';
var_dump($bar == $baz); // false
var_dump($bar);
var_dump($baz);
?>
คำตอบทั้งหมดไม่สนใจปัญหาที่เป็นอันตรายด้วย === มันได้รับการบันทึกในการผ่าน แต่ไม่เน้นว่าจำนวนเต็มและสองครั้งนั้นเป็นประเภทที่แตกต่างกันดังนั้นรหัสต่อไปนี้:
$n = 1000;
$d = $n + 0.0e0;
echo '<br/>'. ( ($n == $d)?'equal' :'not equal' );
echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );
ให้:
equal
not equal
โปรดทราบว่านี่ไม่ใช่กรณีของ "ข้อผิดพลาดในการปัดเศษ" ตัวเลขสองตัวนั้นเท่ากันจนถึงบิตสุดท้าย แต่มีชนิดต่างกัน
นี่เป็นปัญหาที่น่ารังเกียจเพราะโปรแกรมที่ใช้ === สามารถทำงานได้อย่างมีความสุขเป็นเวลาหลายปีหากตัวเลขทั้งหมดมีขนาดเล็กพอ (โดยที่ "เล็กพอ" ขึ้นอยู่กับฮาร์ดแวร์และระบบปฏิบัติการที่คุณใช้งาน) อย่างไรก็ตามถ้าบังเอิญมีจำนวนเต็มที่มากพอที่จะแปลงเป็นสองเท่าชนิดของมันจะถูกเปลี่ยนเป็น "ถาวร" แม้ว่าการดำเนินการที่ตามมาหรือการดำเนินงานจำนวนมากอาจนำกลับไปเป็นค่าจำนวนเต็มเล็กน้อย และมันแย่ลงเรื่อย ๆ มันสามารถแพร่กระจาย - การติดเชื้อสองครั้งสามารถส่งผ่านไปยังสิ่งที่มันสัมผัสการคำนวณครั้งละหนึ่ง
ในโลกแห่งความเป็นจริงสิ่งนี้น่าจะเป็นปัญหาในโปรแกรมที่จัดการกับวันที่เกินปี 2581 เป็นต้น ในเวลานี้การประทับเวลา UNIX (จำนวนวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC) จะต้องใช้มากกว่า 32 บิตดังนั้นการแสดงจะเปลี่ยนเป็น "วิเศษ" เพื่อเพิ่มเป็นสองเท่าในบางระบบ ดังนั้นหากคุณคำนวณความแตกต่างระหว่างสองครั้งคุณอาจสิ้นสุดด้วยสองสามวินาที แต่เป็นสองเท่าแทนที่จะเป็นผลลัพธ์จำนวนเต็มที่เกิดขึ้นในปี 2560
ฉันคิดว่ามันแย่กว่าการแปลงระหว่างสตริงและตัวเลขเพราะมันบอบบาง ฉันคิดว่ามันง่ายในการติดตามว่าสตริงคืออะไรและอะไรคือตัวเลข แต่การติดตามจำนวนบิตในจำนวนนั้นเกินกว่าฉัน
ดังนั้นในคำตอบข้างต้นมีบางตารางที่ดี แต่ไม่มีความแตกต่างระหว่าง 1 (เป็นจำนวนเต็ม) และ 1 (บอบบางเล็กน้อย) และ 1.0 (ชัดเจนสองครั้ง) นอกจากนี้คำแนะนำที่คุณควรใช้เสมอ === และไม่เคย == ไม่ดีเพราะบางครั้ง === จะล้มเหลวโดยที่ == ทำงานได้อย่างถูกต้อง นอกจากนี้จาวาสคริปต์ยังไม่เทียบเท่าในเรื่องนี้เพราะมันมีประเภทตัวเลขเพียงหมายเลขเดียว (ภายในอาจมีการแทนค่าบิตที่ชาญฉลาดแตกต่างกัน แต่ก็ไม่ได้ทำให้เกิดปัญหา ===)
คำแนะนำของฉัน - ไม่ใช้ คุณต้องเขียนฟังก์ชันเปรียบเทียบของคุณเองเพื่อแก้ไขระเบียบนี้
มีสองความแตกต่างระหว่าง==
และ===
ใน PHP อาร์เรย์และวัตถุที่ฉันคิดว่าไม่ได้พูดถึงที่นี่; สองอาร์เรย์ที่มีการเรียงลำดับคีย์ที่แตกต่างกันและวัตถุ
หากคุณมีอาเรย์ที่มีการเรียงลำดับคีย์และอาเรย์อื่นที่มีการเรียงลำดับคีย์ที่แตกต่างกันจะมีความแตกต่างอย่างเคร่งครัด (เช่นการใช้===
) ซึ่งอาจทำให้เกิดถ้าคุณทำการเรียงลำดับคีย์และลองเปรียบเทียบอาเรย์ที่เรียงกับแบบดั้งเดิม
ตัวอย่างเช่นพิจารณาอาร์เรย์ว่าง อันดับแรกเราพยายามที่จะส่งดัชนีใหม่ไปยังอาร์เรย์โดยไม่มีการเรียงลำดับพิเศษ ตัวอย่างที่ดีคืออาร์เรย์ที่มีสตริงเป็นกุญแจ ตอนนี้ลึกเข้าไปในตัวอย่าง:
// Define an array
$arr = [];
// Adding unsorted keys
$arr["I"] = "we";
$arr["you"] = "you";
$arr["he"] = "they";
ตอนนี้เรามีอาร์เรย์ที่ไม่เรียงลำดับคีย์ (เช่น 'เขา' มาหลังจาก 'คุณ') พิจารณาอาร์เรย์เดียวกัน แต่เราเรียงลำดับคีย์ตามตัวอักษร:
// Declare array
$alphabetArr = [];
// Adding alphabetical-sorted keys
$alphabetArr["I"] = "we";
$alphabetArr["he"] = "they";
$alphabetArr["you"] = "you";
ปลาย : คุณสามารถเรียงลำดับอาร์เรย์โดยคีย์โดยใช้ksort ()ฟังก์ชั่น
ตอนนี้คุณมีอาร์เรย์อื่นที่มีการเรียงลำดับคีย์ที่แตกต่างจากอันแรก ดังนั้นเราจะเปรียบเทียบพวกเขา:
$arr == $alphabetArr; // true
$arr === $alphabetArr; // false
หมายเหตุ : มันอาจจะชัดเจน แต่การเปรียบเทียบทั้งสองแตกต่างกันfalse
อาร์เรย์การเปรียบเทียบการใช้อย่างเคร่งครัดเสมอผล อย่างไรก็ตามสองอาร์เรย์โดยพลการอาจจะเท่ากันโดยใช้===
หรือไม่
คุณจะพูดว่า: "ความแตกต่างนี้เล็กน้อย" จากนั้นฉันก็บอกว่ามันเป็นความแตกต่างและควรได้รับการพิจารณาและอาจเกิดขึ้นได้ทุกเวลา ดังกล่าวข้างต้นการเรียงลำดับคีย์ในอาร์เรย์เป็นตัวอย่างที่ดีของสิ่งนั้น
เก็บไว้ในใจสองวัตถุที่แตกต่างกันจะไม่เข้มงวดเท่ากัน ตัวอย่างเหล่านี้จะช่วย:
$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;
// Comparing
$stdClass1 == $stdClass2; // true
$stdClass1 === $stdClass2; // false
$stdClass1 == $clonedStdClass1; // true
$stdClass1 === $clonedStdClass1; // false
หมายเหตุ : การกำหนดวัตถุให้กับตัวแปรอื่นจะไม่สร้างสำเนา แต่เป็นการสร้างการอ้างอิงไปยังตำแหน่งหน่วยความจำเดียวกับวัตถุ ดูที่นี่
หมายเหตุ : ตั้งแต่ PHP7 จะมีการเพิ่มคลาสที่ไม่ระบุชื่อ จากผลลัพธ์ไม่มีความแตกต่างระหว่างnew class {}
และnew stdClass()
ในการทดสอบข้างต้น