logo

相等,还是不等(3) - 真真假假

入门。

布尔值(boolean)分真(true)和假(false)。而其他类型的变量也可以用来判断真假,比如 JavaScript 中以下值会被当做“假”(falsy values):

  • false
  • 0 (zero)
  • "" (empty string)
  • null
  • undefined
  • NaN (Not A Number)

其他的值则被当做“真”。

PHP 里定义以下为假:

  • null // null
  • 0 // integer
  • 0.0 // float
  • "0" // string
  • "" // empty string
  • false // boolean
  • array() // empty array

他们在ifemptyisset的测试中反馈如下:

VALUE           if()  empty() isset()
-------------------------------------
null            false true    false
0.0             false true    true
"0"             false true    true
""              false true    true
false           false true    true
array()         false true    true
EVERYTHING_ELSE true  false   true

放弃?

0和空字符串""相等吗?

Python 说:不等

>>> 0 == ""
False

Java 说:你疯了吧

jshell> 0 == ""
|  Error:
|  bad operand types for binary operator '=='
|    first type:  int
|    second type: java.lang.String
|  0 == ""
|  ^-----^

JavaScript 说:相等,稳稳的

> 0 == ""
true

所以假的和假的都相等?

> null == undefined
true

但又不全是

> "" == undefined
false
> NaN == false
false

而且自己不等于自己

> NaN === NaN
false

这一点 Java 和 Python 也是一样的

jshell> Double.NaN == Double.NaN
$2 ==> false
>>> float('nan') == float('nan')
False

如果 a 和 b 相等,b 和 c 相等,那 a 和 c 也应该相等,对吗?

$a = ''; $b = 0; $c = '0a';
$a == $b; // true
$b == $c; // true
$c == $a; // false!

进阶!

关于 NaN

在做判断的时候 JavaScript 把 NaN 当做 false

> x = NaN ? 'true' : 'false'
'false'

但不是所有语言都支持

jshell> int x = Double.NaN ? 0 : 1;
|  Error:
|  incompatible types: double cannot be converted to boolean
|  int x = Double.NaN ? 0 : 1;
|          ^--------^

NaN就是跟任何值都不相等,包括他自己

jshell> Double.NaN - Double.NaN
$1 ==> NaN

这里不妨把 INFINITY 也拉进来讨论,看来无穷大也是不能用来计算的

jshell> Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY
$2 ==> NaN

jshell> Double.POSITIVE_INFINITY + Double.POSITIVE_INFINITY
$3 ==> Infinity

jshell> Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY
$4 ==> NaN

nullundefined算是一组,只有他们两个互相相等

> null == undefined
true
> null == null
true
> undefined == undefined
true

== vs ===

JavaScript 和 PHP 中都提供两种判断相等的方法:=====

==只判断值是不是相等,如果等号两侧是不一样的类型,他们会被转换成相同的类型进行比较,所以是不具有传递性的,才会出现上面 a==b,b==ca!=c 的情况。而===是更严格的比较,既包括类型也包括值,因而是具有传递性的。

> false == 0
true
> false === 0
false

另一组比较

> 1 == '1'
true
> 1 === '1'
false

所以 JavaScript 和 PHP 中要尽量使用三个等号。

此外,在 JavaScript 中,Object,包括 Function Object,只等于它自己:

function factory() {
  return (a, b) => a + b;
}

const sum1 = factory();
const sum2 = factory();

sum1(1, 2); // => 3
sum2(1, 2); // => 3

sum1 === sum2; // => false
sum1 === sum1; // => true