您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JS 中令人脑壳疼的 == 与 === 区别到底是什么?

时间:2019-09-05 16:06:59  来源:  作者:

JS 中令人脑壳疼的 == 与 === 区别到底是什么?

 

曾经对我来说,等于就是等于,所以第一次接触到 JS 中的三等号时我感到很困惑。大部分编程语言中都有双等号"==",但没有三等号"==="。

下面是一个比较官方的双等号与三等号的差别:

"如果需要判断运算数是否为同一类型并且值相等,则使用严格相等运算符[===]。

否则,使用标准相等运算符[==],它允许你比较两个运算数的值,即使它们类型不同。"

--MDN web docs

 

在认为理解它的关键就在于了解“类型强制转换”,它是“动态类型语言” Vanilla JAVAScript 中的一个奇怪的概念。

之所以会有类型强制转换是因为 JS 想要防御编程错误,比如拿一个数字和一个字符串比较:

“当在 JavaScript 中使用双等号时我们测试的是不严格的相等。双等号还会带来类型强制转换。

 

强制转换的意思是只有当运算数被转换为相同类型时它们才能被比较。”

 

换句话说,由于有类型转换,不同类型的值可以通过 == 被比较,但一个字符串和一个数字则永远不会用 === 严格相等。

举个例子:

  •  
console.log(Number("7") - 7 == 0); // true
console.log(Number("7") - 7 === 0); // true
console.log(Number("7") - 7 === Number("0")); // true
console.log("7" - 7 == "0"); // true
console.log("7" - 7 === "0"); // false

 

JavaScript 中的真与假

 

在 JavaScript 中我们有六个代表假的值:false, 0, ""(空字符串),null, undefined 和 NaN(Not A Number),这六个假值互相是什么关系呢?

“将 false,0和""用(==)相比较,结果为真,它们都不严格相等;null 和 undefined 只和自己相等;NaN 不与任何假值相等,包括它自己。”

  •  
// All permutations of falsy comparisons in JavaScript by Dr. Derek Austin 
console.log(false == false); // true
console.log(false === false); // true
console.log(false == 0); // true -- false, 0, and "" are loosely equal
console.log(false === 0); // false
console.log(false == ""); // true -- false, 0, and "" are loosely equal
console.log(false === ""); // false
console.log(false == null); // false
console.log(false === null); // false
console.log(false == undefined); // false
console.log(false === undefined); // false
console.log(false == NaN); // false
console.log(false === NaN); // false
console.log(0 == 0); // true
console.log(0 === 0); // true
console.log(0 == ""); // true -- false, 0, and "" are loosely equal
console.log(0 === ""); // false
console.log(0 == null); // false
console.log(0 === null); // false
console.log(0 == undefined); // false
console.log(0 === undefined); // false
console.log(0 == NaN); // false
console.log(0 === NaN); // false
console.log("" == ""); // true
console.log("" === ""); // true
console.log("" == null); // false
console.log("" === null); // false
console.log("" == undefined); // false
console.log("" === undefined); // false
console.log("" == NaN); // false
console.log("" === NaN); // false
console.log(null == null); // true
console.log(null === null); // true
console.log(null == undefined); // true -- null loosely equals undefined
console.log(null === undefined); // false
console.log(null == NaN); // false
console.log(null === NaN); // false
console.log(undefined == undefined); // true
console.log(undefined === undefined); // true
console.log(undefined == NaN); // false
console.log(undefined === NaN); // false
console.log(NaN == NaN); // false -- NaN nothing equals NaN, and
console.log(NaN === NaN); // false -- NaN doesn't equal itself

 

虽然 JS 中的假值这么奇葩,但幸好除了这些假值以外所有值都为真:

“在 JavaScript 中,真值就是在布尔类型上下文中所有被认为是"true"的值。所有的值皆为真,除非它被定义为假,比如 false,0,"",null,undefined 和 NaN。”

 

ECMAScript 中的情况呢?

 

如果你感兴趣的话,下面是 JavaScript 所使用的具体算法

严格相等运算符

严格相等运算符(=== 与 !==)使用严格相等比较算法来比较两个运算数:

  •  
11.9.6 严格相等比较算法
当比较 x===y 时,x 与 y 为值,表达式返回 true 或 false,表达式执行方式如下:
1. 如果 Type(x) 和 Type(y) 不同, 返回 false.
2. 如果 Type(x) 为 Undefined, 返回 true.
3. 如果 Type(x) 为 Null, 返回 true.
4. 如果 Type(x) 为数字,那么
→ a. 如果 x 为 NaN, 返回 false.
→ b. 如果 y 为 NaN, 返回 false.
→ c. 如果 x 与 y 的数字值相等, 返回 true.
→ d. 如果 x 为 +0 而 y 为 −0, 返回 true.
→ e. 如果 x 为 −0 而 y 为 +0, 返回 true.
→ f. 返回 false.
5. 如果 Type(x) 为字符串,如果 x 与 y 中的字符顺序完全相同(长度相同,字符位置相同),则返回 true;否则返回 false.
6. 如果 Type(x) 为布尔类型, 如果 x 与 y 皆为真或假,则返回 true;否则,返回 false.
7. 如果 x 和 y 引用了同一个对象,返回 true;否则返回 false.
NOTE — This algorithm d如果fers from the SameValue Algorithm (9.12) in its treatment of signed zeroes and NaNs.

 

标准相等运算符

标准相等运算符(== 和 !=)使用抽象相等比较算法来比较两个运算数:

  •  
11.9.3 抽象相等比较算法(Abstract Equality Comparison Algorithm)
比较 x == y, x 和 y 为值, 表达式返回 true 或 false. 表达式执行如下:
1. 如果 Type(x) 与 Type(y) 相同, 那么
→ a. 如果 Type(x) 为 Undefined, 返回 true.
→ b. 如果 Type(x) 为 Null, 返回 true.
→ c. 如果 Type(x) 为数字, 则
→ → i. 如果 x 为 NaN, 返回 false.
→ → ii. 如果 y 为 NaN, 返回 false.
→ → iii. 如果 x 与 y 数字值相等, 返回 true.
→ → iv. 如果 x 为 +0 并且 y 为 −0, 返回 true.
→ → v. 如果 x 为 −0 并且 y 为 +0, 返回 true.
→ → vi. 返回 false.
→ d. 如果 Type(x) 是字符串, 如果 x 与 y 中的字符顺序完全相同(长度相同,字符位置相同),则返回 true;否则返回 false.
→ e. 如果 Type(x) 为布尔类型, 如果 x 与 y 皆为真或假,则返回true;否则返回 false.
→ f. 如果 x 与 y 引用了同一个对象,返回 true;否则返回 false.
2. 如果 x 为 null 并且 y 为 undefined, 返回 true.
3. 如果 x 为 undefined 并且 y 为 null, 返回 true.
4. 如果 Type(x) 为数字并且 Type(y) 为字符串, 返回 x == ToNumber(y) 的结果.
5. 如果 Type(x) 为字符串并且 Type(y) 为数字, 返回 ToNumber(x) == y 的结果.
6. 如果 Type(x) 为布尔类型, 返回 ToNumber(x) == y 的结果.
7. 如果 Type(y) 为布尔类型, 返回 x == ToNumber(y) 的结果.
8. 如果 Type(x) 为数字或字符串,并且 Type(y) 为 Object, 返回 x == ToPrimitive(y) 的结果.
9. 如果 Type(x) 为 Object 并且 Type(y) 为数字或字符串, 返回 ToPrimitive(x) == y 的结果.
10. 返回 false.
NOTE 1 — Given the above definition of equality:
• String comparison can be forced by: "" + a == "" + b.
• Numeric comparison can be forced by: +a == +b.
• Boolean comparison can be forced by: !a == !b.
NOTE 2 — The equality operators maintain the following invariants:
• A != B is equivalent to !(A == B).
• A == B is equivalent to B == A, except in the order of evaluation of A and B.
NOTE 3 The equality operator is not always transitive. For example, there might be two distinct String objects, each representing the same String value; each String object would be considered equal to the String value by the == operator, but the two String objects would not be equal to each other. For example:
• new String("a") == "a" and "a" == new String("a")are both true.
• new String("a") == new String("a") is false.
NOTE 4 Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode spec如果ication. Therefore Strings values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form.

 

结论

 

通常来说,我比较喜欢用 === 和 !==,除非碰到了必须使用 == 和 != 的情况,比如检查空值。

另外,在检查空值时,牢记 null 和 undefined 使用双等号比较时是相等的这点很有用。



Tags:JS   点击:()  评论:()
声明:本站部分内容来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除,谢谢。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
浏览器加载页面是按从上到下顺序加载的。加载 JS 并执行的时候,会阻塞其他资源的加载。这是因为 JS 可能会有 DOM 、样式等等操作,所以浏览器要先加载这段 JS 并执行,再加载放...【详细内容】
2020-05-14   JS  点击:(4)  评论:(0)  加入收藏
今天我将向大家演示如何使用 React Profiler API、Tracing API 以及 User Timing API 来分别追踪 React 的组件渲染、用户交互以及自定义性能指标。...【详细内容】
2020-04-25   JS  点击:(2)  评论:(0)  加入收藏
Java天天 2020-03-11 16:28:57 微服务已成为在 Node.js 中构建可扩展且强大的云应用的主流方法。同时也存在一些门槛,其中一些难点需要你在以下方面做出决策: 组织项目结构...【详细内容】
2020-03-15   JS  点击:(10)  评论:(0)  加入收藏
一千个读者,有一千个哈姆雷特。此系列文章将会从函数的执行机制、鲁棒性、函数式编程、设计模式等方面,全面阐述如何通过 JavaScript 编写高质量的函数。一、引言如何通过 Jav...【详细内容】
2020-03-02   JS  点击:(10)  评论:(0)  加入收藏
数组是 JS 最常见的一种数据结构,咱们在开发中也经常用到,在这篇文章中,提供一些小技巧,帮助咱们提高开发效率。1. 删除数组的重复项 2. 替换数组中的特定值有时在创建代码...【详细内容】
2020-02-26   JS  点击:(3)  评论:(0)  加入收藏
Adonis是一个 Node.js Web 框架,专注于易用性与速度。它甚至是一个全栈 Web 框架,解决了许多 Web 开发难题,提供了一个干净稳定的 API,用于构建 Web 应用和微服务,或者用于 TDD(...【详细内容】
2019-12-24   JS  点击:(22)  评论:(0)  加入收藏
如果您想了解并深入学习 Node.js 那么您首先要做的第一件事就是安装Node.js 。Node.js 环境怎么安装,对于新人来说肯定摸不着头脑。Node 是一个让 JavaScript运行在服务端的...【详细内容】
2019-11-11   JS  点击:(76)  评论:(0)  加入收藏
阅读JavaScript代码时,你有没有感觉: 你几乎不明白代码的作用? 代码使用了很多JavaScript技巧? 命名和编码风格相当随机?这些是编码习惯不良的迹象。在这篇文章中,我描述了JavaScr...【详细内容】
2019-10-28   JS  点击:(26)  评论:(0)  加入收藏
一切皆对象咱们经常听到JS中“一切皆对象”?有没有问想过这是什么意思?其它语言也有“一切皆对象”之说,如Python。但是Python中的对象不仅仅是像JS对象这样的存放值和值的容器...【详细内容】
2019-10-16   JS  点击:(19)  评论:(0)  加入收藏
JS是一门发展迅速的语言,正因如此,有些新的特性和功能,咱们没有办法在第时间内知道。在这篇文章中,咱们主要探讨一些少有人知道的特性还有一些常用技巧。获取查询字符串参数URLS...【详细内容】
2019-10-11   JS  点击:(22)  评论:(0)  加入收藏
作者:HelloGitHub-kalifun这是 HelloGitHub 推出的《讲解开源项目》[1]系列,今天给大家推荐一个JavaScript 开源的文件上传库项目——FilePond一、介绍1.1 FileP...【详细内容】
2019-09-29   JS  点击:(40)  评论:(0)  加入收藏
你可能刚上手 JavaScript,或者只是曾经偶尔用过。不管怎样,JavaScript 改变了很多,有些特性非常值得一用。 这篇文章介绍了一些特性,在我看来,一个严肃的 JavaScript 开发者每天...【详细内容】
2019-09-26   JS  点击:(20)  评论:(0)  加入收藏
我们平时在开发部署 Node.js 应用的过程中,对于应用进程启动的耗时很少有人会关注,大多数的应用 5 分钟左右就可以启动完成,这个过程中会涉及到和集团很多系统的交互,这个耗时...【详细内容】
2019-09-20   JS  点击:(34)  评论:(0)  加入收藏
最近整理了下团队新人文档,对团队内使用的框架 riot.js 这部分内容做了一些总结。本文主要在 riot.js 源码 方面,分析一下 riot.js 的执行原理和使用优化。Riot.js 简介Simple...【详细内容】
2019-09-10   JS  点击:(34)  评论:(0)  加入收藏
曾经对我来说,等于就是等于,所以第一次接触到 JS 中的三等号时我感到很困惑。大部分编程语言中都有双等号"==",但没有三等号"==="。下面是一个比较官方的双等号与三等号的差...【详细内容】
2019-09-05   JS  点击:(40)  评论:(0)  加入收藏
Cookie 为 Web 应用程序保存用户相关信息提供了一种有用的方法。例如,当用户访问咱们的站点时,可以利用 Cookie 保存用户首选项或其他信息,这样,当用户下次再访问咱们的站点时,应...【详细内容】
2019-09-04   JS  点击:(41)  评论:(0)  加入收藏
虽然这是一个很久以前的问题。但是看到好多答案的办法有点太重了,这里分享一个效率更优、资源占用更低的方法。 首先请一定记住,浏览器环境对内存和CPU的消耗都非常严重,模拟浏...【详细内容】
2019-09-03   JS  点击:(182)  评论:(0)  加入收藏
作者:HelloGitHub-kalifun这是 HelloGitHub 推出的《讲解开源项目》[1]系列,今天给大家推荐一个JavaScript 开源的文件上传库项目——FilePond一、介绍1.1 FileP...【详细内容】
2019-09-02   JS  点击:(62)  评论:(0)  加入收藏
本文主要为您介绍 Node.js 的背景及它能做什么,擅长什么,不会涉及到复杂的代码层面的知识讲解,如果你觉得自己很熟悉了,也可以忽略它。作者简介:五月君,Nodejs Developer,热爱技术...【详细内容】
2019-08-30   JS  点击:(49)  评论:(0)  加入收藏
前言自 Node.js 面世以来,它获得了大量的赞美和批判。这种争论会一直持续,短时间内都不会结束。而在这些争论中,我们常常会忽略掉所有语言和平台都是基于一些核心问题来批判...【详细内容】
2019-08-29   JS  点击:(46)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条