JavaScript 有两种比较方式:严格比较运算符和转换类型比较运算符。

在相等运算符中对应 === 、!==和 ==、!=。

先举个栗子

var str = '1'
var num0 = 0
var num1 = 1
var blT = true
var blF = false
var nul = null
var und = undefined
console.log(str == num1) // true
console.log(str == blT) // true
console.log(blT == num1) // true
console.log(blF == num0) // true
console.log(nul == und) // true console.log(str === num1) // false
console.log(str === blT) // false
console.log(blT === num1) // false
console.log(blF === num0) // false
console.log(nul === und) // false

相等操作符(==)会为两个不同类型的操作数进行类型转换,然后进行严格比较。

严格相等操作符(===),一般也叫做全等操作符。会先判断类型,再比较值是否相等。

类型转换

类型转换的途径:

类型(x) 类型(y) 结果
undefined null true
字符串 数字 toNumber(x) == y
布尔值 数字 toNumber(x) == y
对象 字符串/数字 toPrimary(x) == y

对于两个类型不同的操作数比较。

  • 字符串、布尔值都会先转换成数字类型,再做比较。toNumber(x)
  • 对于复杂数据类型,会先将其转换为原始值,之后,再根据上一个规则比较。

    x = toPrimary(obj) ==> toNumber(x)

    而,如何转成原始类型值呢,一般都会自动通过自带的valueOf()方法或者toString()方法实现。如果转换之后非原始值,比较操作会报类型错误。

具体过程:

先执行valueOf方法,如果该方法返回一个原始值,则将这个原始值转换为数字,并返回这个数字,转换过程结束。如果返回非原始值,继续下一步。

否则,执行toString方法,如果该方法返回一个原始值,则将这个原始值转换为数字,并返回这个数字,转换过程结束。如果返回非原始值 ,继续下一步。

以上都没有成功转换为原始值,则抛出一个类型转换错误的异常。

tips: 每个方法只执行一次。不会将方法返回的非原始类型值继续转换。

举个例子说明下,参考于知乎:

原始数据类型(string,number,boolean,null, undefined,symbol)。

复杂数据类型(Object, Function, Array, Date, ...)

基础数据类型的比较,是值的比较,Object对象的比较,则是引用的比较

相等操作符(==),经过类型转换之后,才比较他们的值或者对象值。

对于全等操作符(===),等号两边的值和类型,必须完全相等。

为什么建议使用 ===

1. review代码时候,增加理解时间

在使用了 ==的表达式中,我们需要先理解作者的意图。

  • 想当然的以为都可以。
  • 确实需要通过类型转换来判断。
  • 不应该类型转换,但是写错了。

2. 会判断错误

let num = 2
let obj = {
valueOf: function() {
return 2
}
}
console.log(obj == 2)

输出true,

我们本意是这两者!=,而这里得到的结果是==,这不是我们想要的结果。

3. 会产生异常

let num = 2
let obj = {
valueOf: function() {
return {}
},
toString: function() {
return {}
}
}
console.log(obj === 2)
console.log(obj == 2)

第一行输出:false

第二行输出错误提示:Uncaught TypeError: Cannot convert object to primitive value

通过前面类型转换,可以得知,一般情况下,对象会先转换为原始值。

而其过程是通过自带的valueOf()/toString()先转换为primitive value,再和其他值做比较。

而在这里,我们手动将obj对象的valueOf()/toString()覆盖了,导致无法实现转换为原始值。

一般情况下,建议使用=== ,除非你了解,确实需要类型转换,才使用 ==

条件表达式语句(if、三目运算等)

if (condition) {
statement1
} else {
statement2
}

以上是if语句的基础用法。通过判断condition的布尔值,来决定执行statement1代码块1,还是执行statement2代码块2。

先看下面的例子:

var s = 'str'
var blT = true
var blF = false
if (s) {
console.log('正确')
} else {
console.log('错误')
}
console.log(s == blT)

以上语句,得到的结果是

正确
false

为什么if语句,会执行第一个代码块。而s == blT 却是false呢?

其实,这个就涉及到类型转换的问题了。

输出“正确”:

  • if语句的条件表达式,会自动调用Boolean()转换函数,将这个表达式的结果转换为一个布尔值。
  • Boolean('str') = true

输出false:

  • 根据在上面类型转换那部分所讲,会先调用Number()转换函数转换为数值,之后再比较。
  • Number('str') = NaN
  • Number(true) = 1

图表举例列出常见对象相等情况

普通相等

完全相等

【完】

javascript中!=、!==、==、===操作符总结的更多相关文章

  1. 坑:JavaScript 中 操作符“==” 和“===” 的区别

    标题:JavaScript 中 操作符"==" 和"===" 的区别 记录一些很坑的区别: 1. '' == '0' // false 0 == '' // t ...

  2. JavaScript中+操作符的特殊性

    在JavaScript中+操作符有两个作用: (1)加法运算 (2)字符串连接 在使用+操作符进行运算时,当+操作符两边都是数值类型的时候,进行加法运算; 当+操作符两边有任意一边是字符串,则进行字符 ...

  3. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  4. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  5. Javascript中void操作符

    Javascript中void是一个操作符,该操作符指定要计算一个表达式但是不返回值. void操作符用法格式如下:1.javascript:void (expression)2.javascript ...

  6. javascript 中的new操作符的理解

    new 操作符 在有上面的基础概念的介绍之后,在加上new操作符,我们就能完成传统面向对象的class + new的方式创建对象,在Javascript中,我们将这类方式成为Pseudoclassic ...

  7. javascript中神奇的(+)加操作符

    javascript是一门神奇的语言,这没神奇的语言中有一个神奇的加操作符. 常用的加操作符我们可以用来做: 加法运算,例如:alert(1+2); ==>3 字符串连接,例如:alert(“a ...

  8. [转] JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  9. JavaScript 中的相等操作符 ( 详解 [] == []、[] == ![]、{} == !{} )

    ECMAScript 中的相等操作符由两个等于号 ( == ) 表示,如果两个操作数相等,则返回 true. 相等操作符会先转换操作数(通常称为强制转型),然后比较它们的相等性. 在转换不同的数据类型 ...

  10. 为什么不要在 JavaScript 中使用位操作符?

    如果你的第一门编程语言不是 JavaScript,而是 C++ 或 Java,那么一开始你大概会看不惯 JavaScript 的数字类型.在 JavaScript 中的数字类型是不区分什么 Int,F ...

随机推荐

  1. 017-封装-OC笔记

    学习目标 1.[了解]异常处理 2.[掌握]类方法 3.[掌握]NSString类 4.[掌握]匿名对象 5.[掌握]封装实例变量 6.[掌握]对象之间的关系 一.异常处理 什么是异常? 代码完全符合 ...

  2. 手把手带你画一个漂亮蜂窝view Android自定义view

    上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义vi ...

  3. Mahout 系列之----共轭梯度

    无预处理共轭梯度 要求解线性方程组 ,稳定双共轭梯度法从初始解 开始按以下步骤迭代: 任意选择向量 使得 ,例如, 对 若 足够精确则退出 预处理共轭梯度 预处理通常被用来加速迭代方法的收敛.要使用预 ...

  4. libevent之event_base

    event_base是libevent的事务处理框架,负责事件注册.删除等,属于Reactor模式中的Reactor. event_base结构体 event_base结构体定义于<event_ ...

  5. 【Qt编程】Qt学习之状态栏

    QStatusBar类提供一个水平条来显示状态信息.所谓状态信息,拿个简单的例子来说,当你在word中编辑时,左下角就会出现页面.字数等等信息.状态信息可以分为三类:临时信息,如一般的提示信息:正常信 ...

  6. PHP 与搜索蜘蛛

    本文移到:http://www.phpgay.com/Article/detail/classid/2/id/63.html

  7. Gradle 1.12用户指南翻译——第三十七章. OSGi 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  8. Java泛型type体系

    最近看开源代码,看到里面很多Java泛型,并且通过反射去获取泛型信息.如果说要看懂泛型代码,那还是比较容易,但是如果要自己利用泛型写成漂亮巧妙的框架,那必须对泛型有足够的了解.所以这两三天就不在不断地 ...

  9. 销售行业ERP数据统计分析都有哪些维度?

    场景描述 当前的企业信息化建设主要包括ERP系统.OA系统等.企业希望实现信息系统数据的整合,对企业资源进行分析汇总,方便对企业相关数据的掌控从而便于对业务流程进行及时调整监控. 但是由于系统间数据的 ...

  10. redis持久化AOF与RDB

    RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原 ...