您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > 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   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  Tags: JS  点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  Tags: JS  点击:(58)  评论:(0)  加入收藏
Web 浏览器日益强大,网站和 Web 应用程序的复杂性也在增加。几十年前需要超级计算机的操作现在可以在智能手机上运行,其中之一就是人脸检测。检测和分析人脸的能力非常有用,因...【详细内容】
2021-08-20  Tags: JS  点击:(105)  评论:(0)  加入收藏
1. 前言作为一名前端工程师,必须搞懂JS中的prototype、__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系...【详细内容】
2021-04-20  Tags: JS  点击:(304)  评论:(0)  加入收藏
一般在开发中,查询网络 API 操作时往往是比较耗时的,这意味着可能需要一段时间的等待才能获得响应。因此,为了避免程序在请求时无响应的情况,异步编程就成为了开发人员的一项基...【详细内容】
2021-03-31  Tags: JS  点击:(260)  评论:(0)  加入收藏
数组是 js 中最常用到的数据集合,其内置的方法有很多,熟练掌握这些方法,可以有效的提高我们的工作效率,同时对我们的代码质量也是有很大影响。...【详细内容】
2021-03-04  Tags: JS  点击:(209)  评论:(0)  加入收藏
本人已经过原 Danny Markov 授权翻译在本教程中,我们将学习如何使用 JS 进行AJAX调用。1.AJAX术语AJAX 表示 异步的 JavaScript 和 XML。AJAX 在 JS 中用于发出异步网络请求...【详细内容】
2021-01-12  Tags: JS  点击:(195)  评论:(0)  加入收藏
今天给大家分享一款超优秀的Vue免费开源UI组件库HEYUI。 heyui 一套基于 vue2.x 构建的UI组件库,star高达2.2K+。提供 50 多种丰富的组件,支持全局方法及配置、自定义主题、国...【详细内容】
2020-11-12  Tags: JS  点击:(150)  评论:(0)  加入收藏
作者:前端小混混 来源:前端先锋作用域JavaScript 的变量被作用域所限制,如果超出了作用域,那么变量就没有办法再被使用,这样做的优点是: 可以避免当前的变量转为全局变量 有效限制...【详细内容】
2020-11-09  Tags: JS  点击:(112)  评论:(0)  加入收藏
问:如何用 JS 一次获取 HTML 表单的所有字段 ?考虑一个简单的 HTML 表单,用于将任务保存在待办事项列表中: <form> <label for="name">用户名</label> <input type="text...【详细内容】
2020-10-12  Tags: JS  点击:(76)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(6)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(20)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(35)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(36)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(40)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== &#39;&#39;) { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(51)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条