[Day16] 严格相等 vs 宽松相等

严格相等宽松相等 是 JavaScript 的比较方法,由以下的运算子来比较结果是否相等,并依结果回传布林值

  • === 严格相等运算子
  • !== 严格不相等运算子
  • == 宽松相等运算子
  • != 宽松不相等运算子
console.log(1 === 1); // true - 严格相等
console.log(1 !== 1); // false - 严格不相等

console.log(1 == 1); // true - 宽松相等
console.log(1 != 1); // false - 宽松不相等

严格相等/不相等

严格相等会比较 ===!== 运算子左右两边运算元的 型别,来判定结果,最後依照结果回传布林值

console.log(1 === 1); // true
console.log(1 === '1'); // false

console.log(1 !== 1); // false
console.log(1 !== '1'); // true

严格相等的例外

NaN

NaN (Not a Number) - 意思为 "不是一个数值"

NaNNaN 做比较,严格相等及宽松相等皆会回传 false

console.log(NaN === NaN); // false

console.log(NaN == NaN); // false

+0 与 -0

-0+0 虽然值不同,但比较结果为 true

console.log( -0 === +0); // true
console.log( -0 == +0); // true

// 其他数值范例
console.log( -1 === +1); // false
console.log( -1 == +1); // false

宽松相等/不相等

宽松相等会因做比较的两者型别不同,而做 隐含转型 - 先转换成相同型别再做比较,但并非所有比较都会发生,是有其规则的

以下为宽松相等的运作表 (MDN - 相等比较):

宽松相等以 ==!= 运算子以及左右两边运算元组合而成,先依照规则转型,再与 做比较,最後依照结果回传布林值

console.log(1 == 1); // true
console.log(1 == '1'); // true

console.log(1 != 1); // false
console.log(1 != '1'); // false

宽松相等的规则

布林与字串会转为数字型别

以下为 布林型别字串型别 在比较时,会先转换为 数字型别 的范例:

1. 字串与数字 比较

范例 1-1

字串型别 会先转换成 数字型别,再与 数字型别 相比较

console.log('1' == 1); // true

console.log(Number('1')); // 1 - 数字型别

Number()String() 为型别包裹器,想知道更多可看 Kuro - 基本型别包裹器

范例 1-2

字串 0x11 与数值做比较,会先转为数字型别 17

console.log(17 == '0x11'); // true

0x11 为十六进位,转为十进位为 17

console.log(Number(0x11)); // 17

维基百科 - 十六进位

2. 布林与数字比较

布林型别 会先转换成 数字型别,再与 数字型别 做比较

console.log(Number(true)); // 1 - 数字型别
console.log(Number(false)); // 0 - 数字型别

// 肯定
console.log(true == 1); // true
console.log(false == 1); // false

// 否定
console.log(true != 1); // false
console.log(false != 1); // true

3. 字串与布林比较

范例 3-1

布林型别字串型别 相比较时,两者都会先转成 数字型别 再做比较

// 布林转数值
console.log(Number(true)); // 1 - 数值
console.log(Number(false)); // 0 - 数值

// 字串转数值
console.log(Number('1')); // 1
console.log(Number('0')); // 0

// 肯定
console.log(true == '1'); // true
console.log(false == '0'); // true

// 否定
console.log(true != '1'); // false
console.log(false != '0'); // false
范例 3-2
  • !00 会先转换为 布林值 false
  • !false 再转换为 布林值 true
  • 布林值 true字串 1 相比较则两者都会先转换为数值,因此结果为相等
console.log('1' == !0); // true

console.log(!0); // true
范例 3-3

需要注意的是 字串 true字串 false 转换成数值时会转成 NaN

// 布林转数值
console.log(Number(true)); // 1 - 数值
console.log(Number(false)); // 0 - 数值

// 字串 true、字串 false 转数值
console.log(Number('true')); // NaN
console.log(Number('false')); // NaN

console.log(true == 'true'); // false
console.log(false == 'false'); // false

Null 与 Undefined 不会转为数字型别

NullUndefined 比较时,不会转为数字型别

NullUndefined 比较时只要看对方是否是 NullUndefined 型别,否则结果皆为 false

范例1

虽然用 Number(null) 可得出 数值 0,但因 NullUndefined 不会转为数字型别比较,此例中得出结果为 false

console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN

console.log(null == 0); // false

范例2

在宽松相等下 NullUndefined 比较结果为 true

console.log(null == undefined); // true
console.log(null === undefined); // false

物件的比较

当物件与非物件做比较时,会使用包裹物件做转换,可参考上面宽松相等运作图表 ToPrimitive(),它会透过 .toString().valueOf() 方法转换後再做比较,而物件与物件则是比较所参考的物件,而非它们的值

{} 物件[] 阵列 皆是属於物件型别

1. 物件与数值比较

此例中 阵列 [10] 使用包裹物件方式先转换为原始型别,再做比较

console.log(10 == [10]); // true

2. 物件与字串比较

当物件与字串做比较,物件会先使用 .toString() 转换物件

范例2-1

阵列 ['A'] 会先转换为字串再与字串做比较

console.log(['A'].toString()); // A

console.log('A' == ['A']); // true
范例2-2

物件 {A: 'A'} 转为字串会显示 [object Object],所以会与 字串 [object Object] 相等

console.log([{A: 'A'}].toString()); // [object Object] - 字串型别

console.log('[object Object]' == {A: 'A'}); // true

3. 物件与布林比较

物件型别布林型别 做比较时,物件型别会透过包裹物件做转换,布林型别则会转为数字型别,再互相做比较

console.log([0] == false); // true

4. 物件与 Null、Undefined 比较

NullUndefined 比较时只要看对方是否是 NullUndefined 型别,否则结果皆为 false

console.log(['null'] == null); // false
console.log(['undefined'] == undefined); // false

5. 物件与物件比较

物件与物件在相比时,比较的不是里面的值,是两者的参考位置,所以当物件与物件比较结果为 false,主因是两个的参考物件不同

范例5-1

虽然以下范例的值相同,但因参考物件不同,所以比较结果为 false

console.log({} == {}); // false

console.log([] == []); // false
范例5-2

变数 b 所取得的是 变数 a 的参考位置,两者指向同个物件,所参考物件相同,所以 变数 a变数 b 比较为 true

// 物件{} 范例
var a = {};
var b = a;
console.log(a == b); // true
console.log(a === b); // true
// 阵列[] 范例
var a = [];
var b = a;
console.log(a == b); // true
console.log(a === b); // true

小测验

console.log(0 == false); // number == number => true
console.log(0 == '0'); // number == number => true
console.log(0 == NaN); // 看对方是否是Null与Undefined => false
console.log(0 == undefined); // 看对方是否是 Null 与 Undefined => false

console.log('' == 0); // number == number => true
console.log('0' == ''); // string == string => false
console.log('' == false); // number == number => true
console.log('' == NaN); // 看对方是否是 Null 与 Undefined => false
console.log('' == undefined); // 看对方是否是 Null 与 Undefined => false

console.log(null == undefined); // 看对方是否是 Null 与 Undefined => true
console.log(null == false); // 看对方是否是 Null 与 Undefined => false
console.log(undefined == false); // 看对方是否是 Null 与 Undefined => false
console.log(null == [null]); // 看对方是否是 Null 与 Undefined => false
console.log(undefined == [undefined]); // 看对方是否是 Null 与 Undefined=>false

console.log([] == 0); // 物件转字串再转数值,number == number => true
console.log({} == 0); // [object, object] == 0 => false
console.log([] == ''); // 物件转字串,string == string => true
console.log({} == ''); // 物件转字串,[object, object] == string => false
console.log([] == false); // 物件转数值,布林转数值,number == number => true
console.log({} == false); // 布林转数值,[object, object] == number => false

参考文献

六角学院 - JavaScript 核心篇

MDN - 相等比较


<<:  Day16-Kubernetes 那些事 - Resource Quotas

>>:  Day 21 HTML5 <HTML5 多媒体标签>

[Day 29] Optimize Images

取自 Artifact Austin: Leaving Pixels Behind - Todd ...

Day07 - Python基本语法 Part 4,模组、档案处理与多执行绪

范例程序主要来自於W3Schools。 模组 建立模组:新增一个.py档,使用欲使用的模组名称命名(...

Day 17 - 取得帐务相关资讯 (下)

官方说明文件:https://sinotrade.github.io/tutor/accountin...

Day-9 Excel筛选大秘辛

今日练习档 ԅ( ¯་། ¯ԅ) 经过昨天的排序介绍後,今天就来到了排序後通常会进行的「筛选」,接着...

D19 第九周 後端基础 PHP 与 MySQL

这周新接触到 PHP 和 MySQL,然後是第一次使用到 session 机制实作登入功能 我自己的...