==和===的区别是什么?

松==比较究竟是如何工作的? 严格的===比较到底是如何工作的?

有什么有用的例子吗?


当前回答

关于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');
}

其他回答

运算符==在两个不同类型之间进行类型强制转换,而===运算符执行“类型安全比较”。这意味着只有当两个操作数具有相同的类型和相同的值时,它才返回true。

例子:

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)

关于对象比较的其他答案的补充:

==使用对象的名称和它们的值来比较对象。如果两个对象具有相同的类型并且具有相同的成员值,$a == $b的结果为true。

===比较对象的内部对象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

变量有类型和值。

$var = "test"是一个包含"test"的字符串 $var2 = 24是一个整数,其值为24。

当您使用这些变量(在PHP中)时,有时您没有好的类型。 例如,如果你这样做

if ($var == 1) {... do something ...}

PHP必须将$var转换为整数。在本例中,"$var == 1"为真,因为任何非空字符串都被转换为1。

当使用===时,检查值和类型是否相等,因此"$var === 1"为假。

这很有用,例如,当你有一个函数可以返回false(错误)和0(结果):

if(myFunction() == false) { ... error on myFunction ... }

这段代码是错误的,如果myFunction()返回0,它被强制转换为false,你似乎有一个错误。正确的代码是:

if(myFunction() === false) { ... error on myFunction ... }

因为测试的是返回值“是一个布尔值并且为假”,而不是“可以被强制转换为假”。

在PHP数组和对象中,==和===之间有两个没有人提到的区别:两个具有不同键排序的数组和对象。

两个具有不同键排序的数组

如果你有两个数组,它们的键排序不同,但有相同的键值映射,它们是严格不同的(即使用===)。这可能会导致问题,如果你对一个数组进行键排序,并试图将排序后的数组与原始数组进行比较。

例如:

$arrayUnsorted = [
    "you" => "you",
    "I" => "we",
];

$arraySorted = $arrayUnsorted;
ksort($arraySorted);

$arrayUnsorted == $arraySorted; // true
$arrayUnsorted === $arraySorted; // false

对象

请记住,主要规则是两个不同的对象永远不会严格相等。请看下面的例子:

$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;

$stdClass1 == $stdClass2; // true
$stdClass1 === $stdClass2; // false
$stdClass1 == $clonedStdClass1; // true
$stdClass1 === $clonedStdClass1; // false

注意:将一个对象赋值给另一个变量并不会创建一个副本——相反,它创建了对同一对象的引用。在这里看到的。

注意:从PHP7开始,引入了匿名类。在上面的测试中,新类{}和新stdClass()之间没有区别。

到目前为止,所有的答案都忽略了一个危险的问题===。这里已经顺便提过,但没有强调,integer和double是不同的类型,所以代码如下:

$n = 1000;
$d = $n + 0.0e0;
echo '<br/>'. ( ($n ==  $d)?'equal' :'not equal' );
echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );

给:

 equal
 not equal

请注意,这不是一个“舍入误差”的情况。这两个数字直到最后一位都完全相等,但它们的类型不同。

This is a nasty problem because a program using === can run happily for years if all of the numbers are small enough (where "small enough" depends on the hardware and OS you are running on). However, if by chance, an integer happens to be large enough to be converted to a double, its type is changed "forever" even though a subsequent operation, or many operations, might bring it back to a small integer in value. And, it gets worse. It can spread - double-ness infection can be passed along to anything it touches, one calculation at a time.

在现实世界中,例如,在处理2038年之后的日期的程序中,这可能是一个问题。此时,UNIX时间戳(1970-01-01 00:00:00 UTC以来的秒数)需要超过32位,因此在某些系统上,它们的表示将“神奇地”切换为两倍。因此,如果你计算两次时间的差值,你可能会得到几秒,但结果是双倍,而不是2017年的整数结果。

我认为这比字符串和数字之间的转换更糟糕,因为它很微妙。我发现记录什么是字符串,什么是数字很容易,但是记录数字中的比特数却超出了我的能力。

因此,在上面的答案中有一些不错的表,但在1(作为整数)和1(微妙的双精度)和1.0(明显的双精度)之间没有区别。另外,总是使用===而从不使用==的建议也不是很好,因为===有时会在==正常工作的地方失败。此外,JavaScript在这方面是不等效的,因为它只有一种数字类型(在内部它可能有不同的位表示,但它不会导致===的问题)。

我的建议是——两者都不要用。你需要编写自己的比较函数来解决这个问题。