原文地址:落明的博客,转载请注明出处!

一、前言

作为一个程序员,我想大家在第一次看到 a = b 的语句时一定是懵逼的。后来才知道 = 在编程语言中是用来赋值的,而不是用来判断两个值是否相等。

那该怎么判断两个值是否相等呢?在 C 或 java 中,是使用 == 来进行比较,而 JavaScript 就有意思了,除了使用 == , 还加了 ===

二、区别与选择

  1. 它们有什么区别?

    具体的区别就一句话:== 在比较时允许进行强制类型转换,而 === 不允许。

    很多人都担心 == 做的事情多一些会不会影响比较的速度,说实话,会的,但影响是微秒级别的,完全可以忽略不计。

    不难看出,== 像是 === 的一种更深入的扩展,因此,满足 === 的值一定满足 ==,反之则不成立。

  2. 该如何选择使用它们?

    很多人会建议你坚持使用 === 而不使用 ==, 我认为这是不明智的,有些时候,比如说处理后端返回的数据时,你无法保证对方传来的值到你进行比较的时候还是预期的那样,此时我觉得完全在可以适当的使用 == 来进行兼容。

    总的来说,当你真的确定进行比较的值是类型相同的,那就使用 ===,否则,除了几种特殊情况,使用 == 并没有什么问题 。

三、=== 的比较规则

  1. 基本类型值的比较

    === 的比较规则很简单,对于非对象类型的值,先判断两边的操作数是否是同一类型,如果是,则进行比较,否则,直接返回 false

    但有两个例外情况:NaN === NaN+0 === -0

    // 不同类型
    '12' === 12; // false
    'a' === true; // false
    null === '12' // false
    null === undefined; // false// 同类型
    1 === 1; // true
    'a' === 'a'; // true
    false === false; // true
    null === null; // true//特殊情况
    NaN === NaN; // false
    +0 === -0 // true
    复制代码
  2. 引用类型值的比较

    对于包含引用类型值的比较,仍然会先判断两边的数据类型,如果只有一个是引用类型值,则直接返回 false,如果两边均是引用类型值,则会比较他们的引用地址是否一致。

    const a = {m: 'string',n: 12
    };
    const b = {m: 'string',n: 12
    };
    const c = 12;a === b; // false
    a === c ; // falseconst d = a;
    a === d; // true
    复制代码

四、== 的比较规则

一开始说过了,在使用 == 进行比较时,运行对两边的操作数进行强制类型转换,那么问题来了,什么情况下会进行转换?不同类型的转换规则又是怎样?

MDN 中有这样一张表,用来展示不同类型值进行 == 判断时的转换规则。

乍一看可能会觉得很乱,但仍然是可以分几种情况来概括这些情况。

在具体分析之前,建议先阅读上一篇文章 显式 (名义) 与 隐式 (鸭子)类型转换 ,因为上图中你能看到有诸如 isFalsy()ToNumber()ToString()ToPrimitive 等抽象方法,使用它们只是为了让大家知道强制转换的方向和结果,而这些也都是上一篇文章讲到的内容。

  1. UndefinedNull 与其它类型值的比较

    我们看前两行和前两列可以发现:它们只和自身及对方相等,与其他类型值比较均返回 false ....这个大概就是传说中的「黑风双煞」吧!

    大家可能会看到 Object 有一个 isFalse() 方法,这个方法是用来判断参数值是否是假值,这个时候大家可能会有疑问了,对象不是都是真值吗?

    没错,document.all 就是一个假值对象,虽然已经被新的 JavaScript 标准废弃,但你或许会在老的项目中看到它,记住就好。

    由于这俩值的特殊性,后面我们说“其他类型”值的时候是排除这俩类型的。

  2. Number 类型值与其他类型值比较

    除了上面的黑风双煞,Number 算是相等比较时的大哥,谁想和它比较,就得先转成 Number 类型。

  3. Boolean 类型值与其他类型值比较

    既然有大哥,肯定得有小弟,而 Boolean 类型值则一马当先,以身作则,将大哥的原则贯彻到底,堪称模范小弟!

    其他类型值想和 Boolean 值做比较,Boolean 值摇身一变将自己转成了 Number 类型,哎,你说,别人能怎么办?!

    无论别人怎么说,Boolean 只想做一只安静的舔狗,无怨无悔,一生一世。

  4. Object 类型值与其他类型值比较

    Object 作为 JavaScript 中最会伪装自己的一种类型,在比较之前谁也摸不透它们的真实身份。也正因为此,它们的日子过得不尽相同。

    在进行比较时,JavaScript 国王会通过 toPrimitive() 方法来揭开他们的真面目,最终你会发现,它们的真实身份可能是任意的一种基本类型。

    因此,在最终比较时,它们也将以真实身份与其他类型值比较。

  5. String 类型值与其他类型值比较

    对于 String 类型值来说,在进行比较时的日子并不好过,毕竟,黑风双煞惹不起,黑社会说话也得听,唯一能让它感受到生活希望的,就是在与 Object 这个变色龙进行比较的时候了。

    只有 ObjecttoPrimitive() 后转为字符串的时候它们可以以字符串的规则进行比较,否则,它们就要面临黑风双煞或是黑社会。

五、== 正确的使用方法

github 上有位大神总结了下面这张图:

我们可以将此当做一份参考。

其实在实际的使用过程中,只要我们避免一些特殊的情况,== 的使用还是安全的。

下面就是七种所谓的特殊情况。

"0" == false; // true -- 晕!
false == 0; // true -- 晕!
false == ""; // true -- 晕!
false == []; // true -- 晕!
"" == 0; // true -- 晕!
"" == []; // true -- 晕!
0 == []; // true -- 晕!
复制代码

如何避免?两个原则:

  1. 如果两边的值中有 true 或者 false,千万不要使用 ==。
  2. 如果两边的值中有 []、"" 或者 0,尽量不要使用 ==。

六、最后

检验大家成果的时候到了,

  1. 仔细想想上面七种特殊情况的产生原因。
  2. 思考下面这些值的比较结果。
[] == ![]; // ?
2 == [2]; // ?
'' == [null] // ?Number.prototype.valueOf = function() {return 3;
};
new Number( 2 ) == 3; // ?复制代码

33 个 JavaScript 核心概念系列(四): == 与 ===相关推荐

  1. 33 个 JavaScript 核心概念系列(三): 显式 (名义) 与 隐式 (鸭子)类型转换

    原文地址:落明的博客 一. 前言 说实话,JavaScript 的类型转换是个相当头疼的问题,无论是对于初学者还是有经验的老司机.它的难处并不在于概念多难理解,而是情况多且杂,看似相同的情况结果却又出 ...

  2. javascript 核心概念(1)-数据类型

    语法 (1)到现在为止,大多数浏览器也还是支持到ECMAScript 第三版的标准. 核心概念就是一个语言的基本工作原理,涉及语法,操作符,数据类型. (2)javascript的一切--变量,函数名 ...

  3. JavaScript 核心概念之作用域和闭包

    相信大家已经阅读了很多关于作用域和闭包文章,我也一样.作用域和闭包是 JavaScript 中的关键概念之一.当我阅读了<高性能的JavaScript>这本书后,我才完全理解这两个概念.所 ...

  4. Spring框架(二) 底层架构核心概念解析-四万字你值得一看

    本篇文章将对Spring底层的一些概念做一些简单的分析 , 也是为了方便后续在阅读源码的时候更加的方便 BeanDefintion BeanDefintion是一个接口 , 它表示一个Bean的定义 ...

  5. [云原生专题-33]:K8S - 核心概念 - 服务Service管理、服务发现、负载均衡

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  6. 学习 JavaScript (四)核心概念:操作符

    JavaScript 的核心概念主要由语法.变量.数据类型.操作符.语句.函数组成,前面三个上一篇文章已经讲解完了.后面三个内容超级多,这篇文章主要讲解的是操作符. 操作符 什么叫做操作符? 这是一种 ...

  7. webpack的四个核心概念

    从 webpack v4.0.0 开始,可以不用引入一个配置文件.然而,webpack 仍然还是高度可配置的.在开始前你需要先理解四个核心概念: 入口(entry) 输出(output) loader ...

  8. Maven——Maven核心概念——史上最烂系列

    Maven 是目前最流行的自动化构建工具,对于生产环境下多框架.多模块整合开发有重要作用.Maven 是一款在大型项目开发过程中不可或缺的重要工具.(自己粗略写了一个SSM项目之后,回顾头来看这个,会 ...

  9. Maven学习总结(四)——Maven核心概念

    2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(四)--Maven核心概念 一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平 ...

最新文章

  1. python插件做nagios发报警邮件二
  2. 每天一个linux命令(20):find命令之exec
  3. oracle 10g视频教程
  4. [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
  5. 作为软件工程师,你必须知道的20个常识
  6. 37条常用Linux Shell命令组合
  7. matlab画置信区间图,matlab绘制带置信区间的双y轴图形 | 学步园
  8. bagging and boosting
  9. python数据分析师工作内容_数据分析师日常工作是什么?
  10. Arduino 极速入门系列 - 光控灯(3) - 光敏电阻、与电阻分压那些事
  11. 二次优化大招(由泰勒公式推出最值条件)
  12. remote addr 取到内网ip_内网穿透工具frp
  13. Linux系统7个运行级别图文详解
  14. linux输出文件没有找到,Linux环境下标准输入、输出、错误信息详解
  15. 【点阵液晶编程连载五】液晶驱动代码的移植
  16. OSO.EXE病毒专杀工具
  17. 201809-1 卖菜
  18. php 字母加1,PHP语法(1)
  19. PhpStorm 配置 Git 教程
  20. LABVIEW 学习-温度采集系统

热门文章

  1. 全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存
  2. python-matplotlib学习(1)
  3. python中的map、filter、reduce函数
  4. Win7下Maven的安装与配置
  5. vfork()系统调用
  6. 3D Game Programming with directx 11 习题答案 8.3
  7. JS中格式化数据保留两位小数
  8. 轻量级Ajax解决方案:Anthem.NET初探
  9. 只有22%的人做对了这道数据分析题,你来试试吗?
  10. 辞旧迎新,胖了几斤?数据告诉你,这种东西你就不该吃