Câu trả lời:
==
và===
Sự khác biệt giữa ==
toán tử bằng nhau lỏng lẻo và ===
toán tử giống hệt nghiêm ngặt được giải thích chính xác trong hướng dẫn :
Toán tử so sánh
┌ ─ ─ Giới thiệu về giới tính của bạn. Ví dụ │ Tên Kết quả ├ ─ ─ Giới thiệu về giới tính của bạn. │ $ a == $ b │ Bằng nhau │ TRUE nếu $ a bằng $ b sau khi tung hứng. │ │ $ a === $ b │ Giống hệt │ THẬT nếu $ a bằng $ b và chúng cùng loại. │ └ ─ ─ Giới thiệu về giới tính của bạn.
==
so sánh bình đẳngNếu bạn đang sử dụng ==
toán tử hoặc bất kỳ toán tử so sánh nào sử dụng phép so sánh lỏng lẻo như !=
, <>
hoặc ==
, bạn luôn phải xem xét bối cảnh để xem cái gì, ở đâu và tại sao một cái gì đó được chuyển đổi để hiểu điều gì đang xảy ra.
Để tham khảo và ví dụ, bạn có thể xem bảng so sánh trong hướng dẫn :
So sánh lỏng lẻo với
==
┌ ─ ─ ┬ ┬─────── │ TRUE FALSE 1 0 -1 │ "1" │ "0" │ "-1" │ NULL │ mảng () "php" │ "" ├ ─ ─ ┼ ┼─────── TRUE TRUE FALSE TRUE │ FALSE TRUE │ TRUE │ FALSE TRUE │ FALSE FALSE TRUE │ FALSE 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 FALSE 0 FALSE TRUE FALSE TRUE │ FALSE FALSE TRUE │ FALSE TRUE │ FALSE TRUE TRUE -1 TRUE FALSE FALSE FALSE TRUE │ FALSE FALSE FUESE FALSE FALSE FALSE "1" TRUE FALSE TRUE │ FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE │ "0" FALSE TRUE │ FALSE TRUE │ FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE │ "-1" TRUE FALSE FALSE FALSE TRUE │ FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE NULL FALSE TRUE FALSE TRUE │ FALSE FALSE FALSE TRUE │ TRUE │ FALSE TRUE Mảng () FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE TRUE │ TRUE SE FALSE FALSE │ "php" TRUE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE "" FALSE TRUE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE TRUE └ ─ ─ ┴ ┴───────
===
so sánh giống hệt nhauNếu bạn đang sử dụng các ===
nhà điều hành, hoặc bất kỳ toán tử so sánh khác trong đó sử dụng so sánh nghiêm ngặt như !==
hoặc ===
, sau đó bạn luôn có thể chắc chắn rằng các loại sẽ không kỳ diệu thay đổi, bởi vì sẽ không có chuyển đổi xảy ra. Vì vậy, với sự so sánh chặt chẽ, loại và giá trị phải giống nhau, không chỉ giá trị.
Để tham khảo và ví dụ, bạn có thể xem bảng so sánh trong hướng dẫn :
So sánh nghiêm ngặt với
===
┌ ─ ─ ┬ ┬─────── │ TRUE FALSE 1 0 -1 │ "1" │ "0" │ "-1" │ NULL │ mảng () "php" │ "" ├ ─ ─ ┼ ┼─────── TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 1 FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 0 FALSE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE -1 FALSE FALSE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE "1" FALSE FALSE FALSE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE FALSE │ "0" FALSE FALSE FALSE FALSE FALSE FALSE TRUE │ FALSE FALSE FALSE FALSE FALSE FALSE │ "-1" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE NULL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE Mảng () FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE │ "php" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE "" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE └ ─ ─ ┴ ┴───────
true
hoặc false
. Thật dễ dàng để đúc. Tất cả các giá trị khác mặc dù có, cho tất cả các mục đích thực tế, hầu như không giới hạn kết hợp. Là "five" == 5
? array(0) == 0
? array(0,0,0) == 0
? 0.0000000000000000000000000000000000000000000000000001 == array()
?
false
cho các mảng khác nhau trong javascript, nhưng true
đối với PHP miễn là giá trị của chúng bằng nhau .
"000" != "00"
, "000" == null
, "000" == false
, "0x0" == false
, array() == 0
, false != null
, array() != null
, false == "0x0"
, false == "000"
. Trong PHP, đó là hành vi ngược lại: "000" == "00"
, "000" != null
, "000" != false
, "0x0" != false
, array() != 0
, false == null
, array() == null
, false != "0x0"
, false != "000"
.
Toán tử == phôi giữa hai loại khác nhau nếu chúng khác nhau, trong khi toán tử === thực hiện 'so sánh an toàn kiểu'. Điều đó có nghĩa là nó sẽ chỉ trả về true nếu cả hai toán hạng có cùng loại và cùng giá trị.
Ví dụ:
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
Cảnh báo : hai trường hợp của cùng một lớp với các thành viên tương đương KHÔNG khớp với ===
toán tử. Thí dụ:
$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
Một bưc tranh đang gia ngan lơi noi:
==
Biểu đồ bình đẳng đôi PHP :===
Biểu đồ ba đẳng thức PHP :Mã nguồn để tạo ra những hình ảnh này:
https://github.com/sentientmachine/php_equality_charts
Những người muốn giữ sự tỉnh táo của họ, không đọc thêm bởi vì điều này sẽ không có ý nghĩa gì, ngoại trừ việc nói rằng đây là cách mà sự điên rồ-fractal, của PHP được thiết kế.
NAN != NAN
nhưng NAN == true
. ==
sẽ chuyển đổi toán hạng trái và phải thành số nếu trái là số. Vì vậy 123 == "123foo"
, nhưng"123" != "123foo"
Một chuỗi hex trong dấu ngoặc kép đôi khi là một dấu phẩy và sẽ được tạo bất ngờ để nổi theo ý bạn, gây ra lỗi thời gian chạy.
==
không phải là bắc cầu bởi vì "0"== 0
, và 0 == ""
nhưng"0" != ""
==
."6" == " 6"
, "4.2" == "4.20"
và, "133" == "0133"
nhưng 133 != 0133
. Nhưng "0x10" == "16"
và "1e3" == "1000"
phơi bày rằng chuyển đổi chuỗi bất ngờ thành bát phân sẽ xảy ra cả mà không có hướng dẫn hoặc sự đồng ý của bạn, gây ra lỗi thời gian chạy.
False == 0
, ""
, []
Và "0"
.
Khi số lượng đủ lớn, chúng là == Infinity.
Một lớp học mới là == đến 1.
Nếu bạn đang sử dụng PHP, bạn sẽ không sử dụng toán tử bằng hai vì nếu bạn sử dụng ba số bằng, các trường hợp cạnh duy nhất phải lo lắng là NAN và các số gần đến vô cùng mà chúng được chuyển thành vô cùng. Với hai lần bằng nhau, bất cứ điều gì cũng có thể gây bất ngờ ==
cho bất cứ điều gì hoặc, hoặc có thể gây bất ngờ đối với ý chí của bạn và !=
với điều gì đó rõ ràng là bằng nhau.
Bất cứ nơi nào bạn sử dụng ==
trong PHP đều có mùi mã xấu vì 85 lỗi trong đó bị phơi bày bởi các quy tắc truyền ngầm ẩn dường như được thiết kế bởi hàng triệu lập trình viên lập trình bằng chuyển động brownian.
Liên quan đến JavaScript:
Toán tử === hoạt động giống như toán tử ==, nhưng nó yêu cầu các toán hạng của nó không chỉ có cùng giá trị mà còn có cùng kiểu dữ liệu.
Ví dụ: mẫu bên dưới sẽ hiển thị 'x và y bằng nhau', nhưng không 'x và y giống hệt nhau'.
var x = 4;
var y = '4';
if (x == y) {
alert('x and y are equal');
}
if (x === y) {
alert('x and y are identical');
}
Một bổ sung cho các câu trả lời khác liên quan đến so sánh đối tượng:
== so sánh các đối tượng bằng cách sử dụng tên của đối tượng và giá trị của chúng. Nếu hai đối tượng cùng loại và có cùng giá trị thành viên, $a == $b
mang lại kết quả đúng.
=== so sánh id đối tượng bên trong của các đối tượng. Ngay cả khi các thành viên bằng nhau, $a !== $b
nếu họ không chính xác cùng một đối tượng.
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
Nói một cách đơn giản nhất:
== kiểm tra nếu tương đương (chỉ giá trị)
=== kiểm tra nếu cùng (giá trị && loại)
Tương đương so với giống nhau: Tương tự
1 + 1 = 2 + 0 (tương đương)
1 + 1 = 1 + 1 (giống nhau)
Trong PHP:
true == 1 (đúng - tương đương về giá trị)
true === 1 (sai - không giống nhau về giá trị && type)
Đó là tất cả về các loại dữ liệu. Lấy một BOOL
ví dụ (đúng hoặc sai):
true
cũng bằng 1
và
false
cũng bằng0
Các ==
không quan tâm đến các kiểu dữ liệu khi so sánh: Vì vậy, nếu bạn đã có một biến đó là 1 (mà cũng có thể là true
):
$var=1;
Và sau đó so sánh với ==
:
if ($var == true)
{
echo"var is true";
}
Nhưng $var
không thực sự bằng nhau true
, phải không? Nó có giá trị int 1
thay vào đó, lần lượt, bằng với true.
Với ===
, các kiểu dữ liệu được kiểm tra để đảm bảo hai biến / đối tượng / bất cứ thứ gì đang sử dụng cùng loại.
Vì vậy, nếu tôi đã làm
if ($var === true)
{
echo "var is true";
}
điều kiện đó sẽ không đúng, vì $var !== true
nó chỉ == true
(nếu bạn hiểu ý tôi).
Tại sao bạn cần điều này?
Đơn giản - chúng ta hãy xem một trong các chức năng của PHP array_search()
::
Các array_search()
chức năng đơn giản là tìm kiếm một giá trị trong một mảng, và trả về chìa khóa của phần tử giá trị được tìm thấy trong. Nếu giá trị không thể được tìm thấy trong mảng, nó sẽ trả về sai . Nhưng, điều gì sẽ xảy ra nếu bạn đã thực hiện array_search()
một giá trị được lưu trữ trong phần tử đầu tiên của mảng (sẽ có khóa mảng 0
) .... array_search()
hàm sẽ trả về 0 ... bằng với sai ..
Vì vậy, nếu bạn đã làm:
$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.
}
Vì vậy, bạn có thấy làm thế nào điều này có thể là một vấn đề bây giờ?
Hầu hết mọi người không sử dụng == false
khi kiểm tra nếu một hàm trả về sai. Thay vào đó, họ sử dụng !
. Nhưng trên thực tế, điều này hoàn toàn giống như sử dụng ==false
, vì vậy nếu bạn đã làm:
$arr = array("name");
if (!array_search("name", $arr)) // This is the same as doing (array_search("name", $arr) == false)
Vì vậy, đối với những thứ như vậy, bạn sẽ sử dụng ===
thay thế, để loại dữ liệu được kiểm tra.
Một ví dụ là thuộc tính cơ sở dữ liệu có thể là null hoặc "":
$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 == là toán tử so sánh so sánh giá trị của các biến. Nhưng === so sánh giá trị và kiểu dữ liệu.
Ví dụ,
<?php
$var1 = 10;
$var2 = '10';
if($var1 == $var2) {
echo 'Variables are equal';
} else {
echo 'Variables are not equal';
}
?>
Trong trường hợp này, đầu ra sẽ là 'Biến bằng nhau', mặc dù kiểu dữ liệu của chúng khác nhau.
Nhưng nếu chúng ta sử dụng === thay vì ==, đầu ra sẽ là 'Biến không bằng nhau'. Đầu tiên php so sánh giá trị của biến và sau đó là kiểu dữ liệu. Ở đây các giá trị là như nhau, nhưng các loại dữ liệu là khác nhau.
Được x = 5
1) Toán tử: == là "bằng". x == 8
là sai
2) Toán tử: === là "chính xác bằng" (giá trị và loại) x === 5
là đúng, x === "5"
là sai
$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
Hãy cẩn thận. Đây là một vấn đề khét tiếng.
// 'test' is found at position 0, which is interpreted as the boolean 'false'
if (strpos('testing', 'test')) {
// code...
}
so với
// true, as strict comparison was made (0 !== false)
if (strpos('testing', 'test') !== false) {
// code...
}
Nói tóm lại, === hoạt động theo cách tương tự mà == thực hiện trong hầu hết các ngôn ngữ lập trình khác.
PHP cho phép bạn thực hiện các so sánh không thực sự có ý nghĩa. Thí dụ:
$y = "wauv";
$x = false;
if ($x == $y)
...
Mặc dù điều này cho phép một số "phím tắt" thú vị, bạn nên cẩn thận vì một hàm trả về thứ gì đó không nên (như "lỗi" thay vì số) sẽ không bị bắt và bạn sẽ không biết chuyện gì đã xảy ra.
Trong PHP, == so sánh các giá trị và thực hiện chuyển đổi loại nếu cần thiết (ví dụ: chuỗi "12343sdfjskfjds" sẽ trở thành "12343" trong so sánh số nguyên). === sẽ so sánh giá trị AND loại và sẽ trả về false nếu loại không giống nhau.
Nếu bạn xem trong hướng dẫn PHP, bạn sẽ thấy rất nhiều hàm trả về "false" nếu hàm bị lỗi, nhưng chúng có thể trả về 0 trong một kịch bản thành công, đó là lý do tại sao chúng khuyên bạn nên thực hiện "if (function ()! == sai) "để tránh sai lầm.
Vài ví dụ
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
== Chỉ so sánh giá trị, nó sẽ không bận tâm về các loại dữ liệu
so với
=== So sánh các giá trị và kiểu dữ liệu
Bạn sẽ sử dụng === để kiểm tra xem một hàm hoặc biến là sai thay vì chỉ tương đương với false (không hoặc chuỗi rỗng).
$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;
}
Trong trường hợp này, strpose sẽ trả về 0, tương đương với sai trong thử nghiệm
if ($pos == false)
hoặc là
if (!$pos)
đó không phải là những gì bạn muốn ở đây.
Về việc khi nào nên sử dụng cái này hơn cái kia, ví dụ như fwrite()
hàm trong PHP.
Hàm này ghi nội dung vào một luồng tệp. Theo PHP, " fwrite()
trả về số lượng byte được ghi hoặc FALSE bị lỗi.". Nếu bạn muốn kiểm tra xem cuộc gọi chức năng có thành công hay không, phương pháp này là thiếu sót:
if (!fwrite(stuff))
{
log('error!');
}
Nó có thể trả về 0 (và được coi là thành công) và tình trạng của bạn vẫn được kích hoạt. Cách đúng sẽ là:
if (fwrite(stuff) === FALSE)
{
log('error!');
}
PHP là một ngôn ngữ gõ lỏng lẻo. Sử dụng toán tử kép bằng nhau cho phép kiểm tra lỏng một biến.
Việc kiểm tra một cách lỏng lẻo một giá trị sẽ cho phép một số giá trị tương tự, nhưng không bằng nhau, tương đương nhau:
Tất cả các giá trị này sẽ tương đương như nhau bằng cách sử dụng toán tử kép bằng nhau.
Các biến có một loại và một giá trị.
Khi bạn sử dụng các biến này (trong PHP), đôi khi bạn không có loại tốt. Ví dụ, nếu bạn làm
if ($var == 1) {... do something ...}
PHP phải chuyển đổi ("sang cast") $ var thành số nguyên. Trong trường hợp này, "$ var == 1" là đúng bởi vì bất kỳ chuỗi không trống nào được chuyển thành 1.
Khi sử dụng ===, bạn kiểm tra xem giá trị VÀ LOẠI có bằng nhau không, vì vậy "$ var === 1" là sai.
Điều này rất hữu ích, ví dụ, khi bạn có một hàm có thể trả về false (lỗi) và 0 (kết quả):
if(myFunction() == false) { ... error on myFunction ... }
Mã này sai như thể myFunction()
trả về 0, nó được chuyển thành false và bạn dường như có lỗi. Mã chính xác là:
if(myFunction() === false) { ... error on myFunction ... }
bởi vì thử nghiệm là giá trị trả về "là boolean và là false" và không "có thể được chuyển thành false".
Các ===
nhà điều hành có nghĩa vụ phải so sánh chính xác bình đẳng nội dung trong khi các ==
nhà điều hành sẽ so sánh bình đẳng ngữ nghĩa. Đặc biệt nó sẽ ép các chuỗi thành số.
Bình đẳng là một chủ đề rộng lớn. Xem bài viết Wikipedia về bình đẳng .
<?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);
?>
Tất cả các câu trả lời cho đến nay đều bỏ qua một vấn đề nguy hiểm với ===. Nó đã được ghi nhận khi truyền, nhưng không nhấn mạnh, số nguyên và số kép là các loại khác nhau, do đó, đoạn mã sau:
$n = 1000;
$d = $n + 0.0e0;
echo '<br/>'. ( ($n == $d)?'equal' :'not equal' );
echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );
cho:
equal
not equal
Lưu ý rằng đây KHÔNG phải là trường hợp "lỗi làm tròn". Hai số chính xác bằng với bit cuối cùng, nhưng chúng có các loại khác nhau.
Đây là một vấn đề khó chịu vì một chương trình sử dụng === có thể chạy rất vui trong nhiều năm nếu tất cả các số đủ nhỏ (trong đó "đủ nhỏ" phụ thuộc vào phần cứng và hệ điều hành bạn đang chạy). Tuy nhiên, nếu tình cờ, một số nguyên đủ lớn để được chuyển đổi thành gấp đôi, loại của nó được thay đổi "mãi mãi" ngay cả khi một hoạt động tiếp theo hoặc nhiều hoạt động có thể đưa nó trở lại một số nguyên nhỏ về giá trị. Và, nó trở nên tồi tệ hơn. Nó có thể lây lan - nhiễm trùng hai lần có thể truyền qua bất cứ thứ gì nó chạm vào, mỗi lần tính toán.
Trong thế giới thực, điều này có khả năng là một vấn đề trong các chương trình xử lý ngày ngoài năm 2038 chẳng hạn. Tại thời điểm này, dấu thời gian UNIX (số giây kể từ 1970-01-01 00:00:00 UTC) sẽ yêu cầu nhiều hơn 32 bit, do đó, đại diện của chúng sẽ "chuyển đổi" một cách kỳ diệu lên gấp đôi trên một số hệ thống. Do đó, nếu bạn tính chênh lệch giữa hai lần, bạn có thể kết thúc với một vài giây, nhưng là gấp đôi, thay vì kết quả số nguyên xảy ra trong năm 2017.
Tôi nghĩ rằng điều này là tồi tệ hơn nhiều so với chuyển đổi giữa các chuỗi và số bởi vì nó là tinh tế. Tôi thấy thật dễ dàng để theo dõi chuỗi là gì và số là gì, nhưng theo dõi số bit trong một số nằm ngoài tôi.
Vì vậy, trong các câu trả lời ở trên có một số bảng hay, nhưng không có sự phân biệt giữa 1 (dưới dạng số nguyên) và 1 (gấp đôi tinh tế) và 1.0 (gấp đôi rõ ràng). Ngoài ra, lời khuyên mà bạn nên luôn luôn sử dụng === và không bao giờ == là không tốt vì đôi khi === sẽ thất bại khi == hoạt động đúng. Ngoài ra, JavaScript không tương đương về mặt này vì nó chỉ có một loại số (bên trong nó có thể có các cách biểu diễn bit-khôn ngoan khác nhau, nhưng nó không gây ra vấn đề cho ===).
Lời khuyên của tôi - sử dụng không. Bạn cần phải viết chức năng so sánh của riêng bạn để thực sự sửa chữa mớ hỗn độn này.
Có hai sự khác biệt giữa ==
và ===
trong các mảng và đối tượng PHP mà tôi nghĩ không đề cập ở đây; hai mảng với các loại khóa và đối tượng khác nhau.
Nếu bạn có một mảng với một loại sắp xếp khóa và một mảng khác với một loại khóa khác, thì chúng hoàn toàn khác nhau (tức là sử dụng ===
). Điều đó có thể gây ra nếu bạn sắp xếp khóa một mảng và cố gắng so sánh mảng đã sắp xếp với mảng ban đầu.
Ví dụ, hãy xem xét một mảng trống. Đầu tiên, chúng tôi cố gắng đẩy một số chỉ mục mới vào mảng mà không có bất kỳ sắp xếp đặc biệt nào. Một ví dụ tốt sẽ là một mảng với các chuỗi là các khóa. Bây giờ đi sâu vào một ví dụ:
// Define an array
$arr = [];
// Adding unsorted keys
$arr["I"] = "we";
$arr["you"] = "you";
$arr["he"] = "they";
Bây giờ, chúng ta có một mảng các khóa không được sắp xếp (ví dụ: 'anh ấy' đến sau 'bạn'). Hãy xem xét cùng một mảng, nhưng chúng tôi đã sắp xếp các khóa theo thứ tự bảng chữ cái:
// Declare array
$alphabetArr = [];
// Adding alphabetical-sorted keys
$alphabetArr["I"] = "we";
$alphabetArr["he"] = "they";
$alphabetArr["you"] = "you";
Mẹo : Bạn có thể sắp xếp một mảng theo khóa bằng hàm ksort () .
Bây giờ bạn có một mảng khác với một loại khóa khác với loại đầu tiên. Vì vậy, chúng tôi sẽ so sánh chúng:
$arr == $alphabetArr; // true
$arr === $alphabetArr; // false
Lưu ý : Có thể rõ ràng, nhưng so sánh hai mảng khác nhau bằng cách sử dụng so sánh nghiêm ngặt luôn cho kết quả false
. Tuy nhiên, hai mảng tùy ý có thể bằng ===
hoặc không sử dụng .
Bạn sẽ nói: "Sự khác biệt này là không đáng kể". Sau đó, tôi nói đó là một sự khác biệt và nên được xem xét và có thể xảy ra bất cứ lúc nào. Như đã đề cập ở trên, sắp xếp các khóa trong một mảng là một ví dụ tốt về điều đó.
Hãy ghi nhớ, hai đối tượng khác nhau không bao giờ nghiêm ngặt - bằng nhau . Những ví dụ này sẽ giúp:
$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;
// Comparing
$stdClass1 == $stdClass2; // true
$stdClass1 === $stdClass2; // false
$stdClass1 == $clonedStdClass1; // true
$stdClass1 === $clonedStdClass1; // false
Lưu ý : Việc gán một đối tượng cho một biến khác không tạo ra một bản sao - thay vào đó, nó tạo ra một tham chiếu đến cùng một vị trí bộ nhớ với đối tượng. Xem ở đây .
Lưu ý : Kể từ PHP7, các lớp ẩn danh đã được thêm vào. Từ kết quả, không có sự khác biệt giữa new class {}
và new stdClass()
trong các thử nghiệm ở trên.