js中=、==、===三剑客

143 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

js中有很多的赋值运算符和操作运算符,其中=、==、===这三个虽然长得像,但是细分的用法还是有很大不同的。本文就试着探讨实际开发过程中,使用这三者的区别。

赋值运算符

"="是典型的赋值运算符,同样的"+="、"*="这些也是。使用=赋值时,如果是基本数据类型,则直接使用内存中的值,没有则新建;如果是引用类型的数据,则赋值的是引用数据在内存中的地址,如果被引用的对象发生了改变,则会影响其他的数据。

let a = 1;
let b = [1,2,3];
a = b;
b[0] = 4;
console.log(a); // [4,2,3]

相等运算符

==、===都属于相等运算符,返回结果为true或者false。其中==表示相等,===表示全等。

== 相等运算符

相等判断的是值是否相等,存在隐式类型转换;如果类型相同,值相等,此时的==可等同于===,否则==不可等价于===。具体的判断规则如下:

比较的双方都是基本数据类型

  • 如果比较的一方是null或者undefined,则另一方也必须是null或者undefined表达式才为true,否则为false。null和undefined可以放在一起比较,因为undefined"继承自"null,并且在比较相等时存在隐式转换,与null进行比较可保护undefined的情况。
null == undefined; // true
let a;
a == null ? 1 : 0; // 1
  • 如果比较的一方是string字符串,则先将字符串隐式转换为number数字,然后再比较;都是字符串则按照字符串的比较
'1' == 1; // true
  • 如果比较的一方是Boolean类型,则先将其隐式转换为number,然后再比较
'1' == true; // '1' --> 1, true --> 1

比较的某一方是引用数据类型

  • 如果比较双方都是引用类型,则比较是否指向同一个对象地址
let a = {x: 100}; // 在内存中创建对象
let b = {x: 100}; // 在内存中创建对象
a == b; // false,两者创建的对象在内存中的地址不一样
  • 如果比较的某一方为引用数据类型,另一方是string、number、symbol等,则先将引用类型转为number或string,然后再比较
{} == {}; // false
{} == !{}; // false

两者看似很像,但是本质上是不一样的。首先第一个,判断两个对象是否相等,是判断两个对象的内存地址是否相同,显然不一样;第二个,{}转换为number时,会返回NaN,!{}则返回0,NaN与任何值比较,包括自己都是返回false

[] == []; // false
[] == ![]; // true

数组和对象都是引用类型,但是结果还是相差有点大。第一个,数组是引用类型,两者比较时内存地址不一样,因此返回false。

第二个,左侧是引用类型,但是右侧是boolean类型,因此从左到右,[]会被转换为0;![]可分为两个部分,先是if([]),返回为true,然后取反,最终![]的结果就为false。[] == ![] ==> 0 == false。其结果就是true

{} == '[object Object]'; // true

{}转换为字符串其实就是'[object Object]',js中字符串的比较其实就是比较值是否相等。

一图胜千言

image.png

=== 全等运算符

全等运算符不仅会比较值,还会比较类型,并且不会有隐式类型转换,这一点与==有很大的不同。因此===也可以被称为“严格相等运算符”。再把上述例子用===判断一下:

null === undefined; // false
'1' === 1; // false
'1' === true; // false
{} === !{}; // false
[] === ![]; // false
{} === '[object Object]'; // false
1 / 0 === 1 / -0; // false; js中0可以作为被除数,且返回最大值或者最小值

总结

  • =是赋值运算符,并且是浅拷贝。如果赋值的是引用数据类型,则需要注意值的变化
  • ==和===是相等运算符。由于==的隐式转换,可能会带来意想不到的bug,因此除非必要或者明确知道隐式转换的范围,能用===的地方就不要使用==来比较
  • 使用==,有可能会造成意想不到的bug。

原创不易,转载请注明出处