Javascript 中 == 和 === 区别是什么?
Javascript 中 == 和 === 区别是什么?
Javascript 中 == 和 === 区别是什么?
双等号会造成类型转换,推荐一律使用三等号
寻寻觅觅一直没有遇到能说服我放弃双等号的答案,还请大家赐教
我的理解:在变量赋值时内存会存储值的类型;做双等号比较操作时,会先做临时类型转换再做比较,内存中存储的值还是原来的不会改变:
不知道我理解是否有误,请赐教
-----------------------------------------------------------------------
感谢回答,我问题没描述清楚,特修改了一下问题
js中使用==会造成类型转换,对后续代码会不会造成意外的影响?
432
69,501
邀请回答
28 个回答
![](https://pic4.zhimg.com/da8e974dc_xs.jpg)
JavaScript 中应该用 "==" 还是 "==="? - 贺师俊的回答
“对后续代码会不会造成意外的影响”?答案是:会。
意外的影响不是指程序执行上的“副作用”,而是指代码意图的实现。
提到的 You don't know JS 是本好书,但是不代表作者的所有观点都是对的。
如果对你来说编程是一项工作,而不仅仅是兴趣爱好,就需要用工程标准进行衡量。而以工程标准衡量,“==”带来的便利性抵不上其带来的成本。
举个简单的例子,团队协作中你肯定需要读别人的代码。而当你看到“==”时,要判断清楚作者的代码意图是确实需要转型,还是无所谓要不要转型只是随手写了,还是不应该转型但是写错了……所花费的脑力和时间比明确的“===”(加上可能需要的明确转型)要多得多。要记得团队中的每个人(包括原作者自己)都需要付出这理解和维护成本。
收藏感谢
![](https://pic2.zhimg.com/ad29fb159725b4d7e904a4c876e0c120_xs.jpg)
var x = 1;
var obj = {valueOf: function(){ x = 2; return 0 }}
console.log(obj == 0, x) // true, 2
甚至还会产生异常呢
var x = 1;
var obj = {valueOf: function(){ return {} }, toString: function(){ return {}}}
console.log(obj == 0) // Error: Cannot convert object to primitive value
————————————————————————————————————————————
这是 ==这是 ===
完整比较图:
- 红色:===
- 橙色:==
- 黄色:<= 和 >= 同时成立,== 不成立
- 蓝色:只有 >=
- 绿色:只有 <=
(参:JS Comparison Table, Edit fiddle - JSFiddle)顺便,有人说这图像现代艺术,感觉旋转完更像,删减重排换成 S1 配色之后做成头像了。
不免费帮人做头像(也就是换个顺序的事情)
收藏感谢收起
![](https://pic3.zhimg.com/13359850d_xs.jpg)
严格运算符的运算规则如下,
(1)不同类型值
如果两个值的类型不同,直接返回false。
(2)同一类的原始类型值
同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。
(3)同一类的复合类型值
两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。
(4)undefined和null
undefined 和 null 与自身严格相等。
null === null //true
undefined === undefined //true
相等运算符在比较相同类型的数据时,与严格相等运算符完全一样。
在比较不同类型的数据时,相等运算符会先将数据进行类型转换,然后再用严格相等运算符比较。类型转换规则如下:
(1)原始类型的值
原始类型的数据会转换成数值类型再进行比较。字符串和布尔值都会转换成数值,所以题主的问题中会有第二个string输出。
(2)对象与原始类型值比较
对象(这里指广义的对象,包括数值和函数)与原始类型的值比较时,对象转化成原始类型的值,再进行比较。
(3)undefined和null
undefined和null与其他类型的值比较时,结果都为false,它们互相比较时结果为true。
(4)相等运算符的缺点
相等运算符隐藏的类型转换,会带来一些违反直觉的结果。
'' == '0' // false
0 == '' // true
0 == '0' // truefalse == 'false' // false
false == '0' // truefalse == undefined // false
false == null // false
null == undefined // true' \t\r\n ' == 0 // true
这就是为什么建议尽量不要使用相等运算符。
至于使用相等运算符会不会对后续代码造成意外影响,答案是有可能会。
var a = undefined;
if(!a){console.log("1"); //1
}
var a = undefined;
if(a == null){console.log("1"); //1
}
var a = undefined;
if(a === null){console.log("1"); //无输出
}
也就是说当a为undefined时,输出的值会有变化,而在编程中对象变成undefined实在是太常见了。
推荐一篇文章运算符 -- JavaScript 标准参考教程(alpha)
收藏感谢收起
![](https://pic3.zhimg.com/c3b8947ea8b30817ca6659f8478ebc7d_xs.jpg)
场景二:你向女神表白,女神说不,转身离开了。
使用 == 的时候,JS 告诉你这两个场景结果是一样的。
这不是坑爹吗?
收藏感谢
1 条评论
![](https://pic2.zhimg.com/v2-bc8bc840c8279ae4e9fd9913e403904c_s.jpg)
啪啪啪小生手16 天前
很好啊!0点见不是就想耍小白嘛!多亏==
评论
![](https://pic4.zhimg.com/da8e974dc_xs.jpg)
题主,我非常推荐你看看这个系列: You Don't Know JS
关于"=="和"===",作者在第一本书的第二章是这样说的:YDKJS | Equality
截取一小段:
Many developers feel that === is more predictable, so they advocate always using that form and staying away from ==. I think this view is very shortsighted. I believe == is a powerful tool that helps your program, if you take the time to learn how it works.
简单翻译一下:
许多开发者认为 === 的行为更加容易预测,所以他们总是主张使用 === 而劝人们远离 ==,我认为这种看法是非常短视的。如果你花点时间来搞清楚它是如何工作的话,== 绝对是一个能够帮助你程序的强大工具。
关于 == 是如何工作的,可以看看链接中的文章,或者直接去看 == 的 ECMAScript Language Specification 的 11.9.3
因为你是一个有质疑精神的人,在JS领域有很多所谓 The Good Part 的部分;大家都推荐你使用JS的这个子集,抛弃一些“奇怪”的特性。在YDKJS这个系列的文章中,作者认为 The Good Part 往往是 The Safe Part;但事实上JS的另一部分同样有趣而值得研究,这个系列就致力于为你展示另一个视角。
我觉得你应该看看。
-------------------------
UPDATE (2015-7-1):
关于你的问题:“js中使用==会造成类型转换,对后续代码会不会造成意外的影响?”
我的答案是不会。
==, >, <, +, -, ...
这些操作符所造成的隐式类型转换都是无副作用的,它不会改变变量本身保存的值。
而递增操作符、递减操作符:
a++ / a--
会有副作用,即表达式执行完后递增/递减1
要解除类似的困惑,简单的方法是自己直接在控制台测一下,想要更全面的了解就直接读相关的标准。
--------------------------
UPDATE (2015-12-23):
经过
提醒,更正一下:“== 是能产生副作用的,如果你覆写某个对象的 valueOf/toString 的话。”
没错,== 的隐式类型变换正是调用了这两个方法,如果在覆盖的方法里写了带有副作用的代码,确实也会导致 == 带来副作用。
例子:
Array.prototype.valueOf = function() {this[0]++;return this;
}
var x = [1, 2, 3];
x == 0;
console.log(x); // [2, 2, 3]
这也侧面印证了,在搞不清后果的情况下,不应该随便修改预定义对象的 prototype 上的方法。
如果不存在例子中这种带有副作用代码的情况,还是可以放心地使用 ==
收藏感谢收起
![](https://pic3.zhimg.com/5683e52a9e3474770e89809198006095_xs.jpg)
一般来说是比较推荐 x==null的做法
没有人说一定使用=== 就好, 至少很多FrameWork 和 Lib 都是用 == 居多
使用==有效避免如下代码:
var a = new String(1)
undefined
a
String {0: "1", length: 1, [[PrimitiveValue]]: "1"}
a=="1"
true
a==="1"
false
很明显 a 就是个货真价实的字符串
收藏感谢
![](https://pic7.zhimg.com/v2-91dc864472b9cb893bbd94c5dc22076c_xs.jpg)
不会。不会对比较变量本身产生形象(除非toString或valueOf方法被覆写成特定用途了)。
不推荐的原因是其逻辑比较难懂,容易疏忽出错。
——
括号的例子:
a={};
a.toString=function(){alert(0);};
a.valueOf=function(){alert(1);a=1;};
a==0;//自动依次触发了以上两个函数
alert(a);//已经是1
收藏感谢
![](https://pic4.zhimg.com/da8e974dc_xs.jpg)
== :相等运算符
=== :我更愿意叫它全等运算符
两者区别:
第一点:前者仅判断数据的值,而后者是先判断数据的类型,相同的前提下在判断数据的值。
第二点:也就是评论中所说的“操作数类型不同时它们的处理方式不同”
先来说一下"=="的情况:
1. 两个不同的基本数据类型 :如果两个基本数据类型不同,会将它们转化为数据类型,再进行比较。
var a = 1;
var b = '1';
var c = true;
alert(a == b); //true
alert(a == c); //true
alert(b == c); //true
2. 一个基本数据类型与一个引用数据类型 :会将对象转化为它的原始值,在与基本数据类型进行比较。
var arr = [1,2];
var str = "1,2";
alert(arr == str); //内部执行valueOf(),将arr值转化为原始值,但是arr并没有变化,显示true
将对象转化为它的原始值,也就是说后台会自动调用Object.prototype.valueOf()方法:
var arr = [1,2];
var str = "1,2";alert(arr.__proto__.hasOwnProperty("valueOf")); //false
alert(Object.prototype.hasOwnProperty("valueOf")); //trueObject.prototype.valueOf = function(){alert("valueOf"); //valueOf
};alert(arr == str); // 因为自己写的valueOf()重新覆盖了Object.prototype.valueOf()方法,所以不能实现原始值的转化,具体请百度valueOf()内部实现机制,所以此处显示false
3. 两个引用类型:判断两者之间的引用地址
var arr1 = [1,2]; //引用地址1
var arr2 = [1,2]; //引用地址2
alert(arr1 == arr2); //两者引用地址不同,显示false
再来说一下"==="的情况:
相对于"=="来说,只要类型不一致,它就直接返回false,并不会像"=="那样去转换类型再比较的情况。
不过还是建议尽量使用"===",因为"=="不严谨,可能会带来一些违反直觉的后果。比如我们常使用的对象,有时获取不到而被赋值为undefine的情况。
var obj = undefined;if(obj == null){console.log("1"); //执行
}if(obj === null){console.log("2"); //不执行
}
收藏感谢收起
![](https://pic4.zhimg.com/da8e974dc_xs.jpg)
undefined == null
false == " \t "
"" == 0
123 == "123"
"1" == true
上面的答案都是true。
虽然你可以说,既然语言这样设计,肯定有它自己的道理啊。但是别忘了,JavaScript 是一个动态类型语言啊,假如你写了这样的代码:
function fix(n) {
if (n == 0) return x + 1;
return x + 2;
}
如果输入n为字符串值"0"的话,恭喜你,你的程序爆炸啦!
你将会得到字符串"01"作为返回值,而不是你想要的数字1。
所以一句话概括:没有类型限制,类型转换的后果将是不可预料的。
而且你写的程序很大的话,你可能在这上面浪费好几个小时找 bug。
所以在自己需求明确的情况下,为什么不写===来避免可能的 bug 呢?
---------平反分割线---------
那么这种不严格比较确实就一无是处吗?不,比如你想判断一个字符串看起来是不是空白的(由空白字符组成),可以这样写:
if (typeof str === "string" && str == false)
console.log("The string is full of white spaces!");
收藏感谢
![](https://pic3.zhimg.com/33b52cbda_xs.jpg)
珍爱生命, 远离 ==
收藏感谢
![](https://pic3.zhimg.com/23e26430cf4da5434055eace38bf665f_xs.jpg)
1. 不会对比较逻辑以外的代码造成影响。
2. 还是推荐使用 === ,除了( x == null )以外。优点是逻辑/语义清晰,可以防止意外的错误。比如 `'1' == 1` 为 true,但这真的是题主期待的行为吗?
另外,如果题主真的想透彻了解 == 和 === 的区别,请阅读ES规范——真的一步一步交代了比较的整个流程。
收藏感谢
![](https://pic3.zhimg.com/aadd7b895_xs.jpg)
“双等号会造成类型转换,推荐一律使用三等号”
这明显是不对的吧!
1、对于string,number等基础类型,==和===是有区别的
1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
2)同类型比较,直接进行“值”比较,两者结果一样
2、对于Array,Object等高级类型,==和===是没有区别的
进行“指针地址”比较
收藏感谢
![](https://pic3.zhimg.com/aadd7b895_xs.jpg)
首先,== equality 等同,=== identity 恒等。
==, 两边值类型不同的时候,要先进行类型转换,再比较。
===,不做类型转换,类型不同的一定不等。
==操作符:
如果两个值具有相同类型,会进行===比较,返回===的比较值
如果两个值不具有相同类型,也有可能返回true
如果一个值是null另一个值是undefined,返回true
如果一个值是string另个是number,会把string转换成number再进行比较
如果一个值是true,会把它转成1再比较,false会转成0
如果一个值是Object,另一个是number或者string,会把Object利用 valueOf()或者toString()转换成原始类型再进行比较
===操作符:
要是两个值类型不同,返回false
要是两个值都是number类型,并且数值相同,返回true
要是两个值都是stirng,并且两个值的String内容相同,返回true
要是两个值都是true或者都是false,返回true
要是两个值都是指向相同的Object,Arraya或者function,返回true
要是两个值都是null或者都是undefined,返回true
收藏感谢
![](https://pic1.zhimg.com/796ebcc54_xs.jpg)
爹===干爹 false
收藏感谢
![](https://pic3.zhimg.com/6eed3196531ce5a98bf50ba06d10d083_xs.jpg)
我知道的除了忽略类型外还有就是双等号不具有传递型,有时候a==b, a==c, 但是b!=c,具体是什么值记不得了,这种情况在《JavaScript语言精粹》中提到过,所以书的作者推荐使用三等号。
-------
放个图:
收藏感谢
![](https://pic1.zhimg.com/665bd18a642421ae71b4ea9b5cb41d6e_xs.jpg)
==其实很好用啊,有一夫当关万夫莫开的快感
收藏感谢
![](https://pic7.zhimg.com/d21627dd8_xs.jpg)
严格相等运算符“===”首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换:
1·如果两个值类型不相同,则它们不相等。
2·如果两个值都是null或者都是undefined,则它们不相等。
3·如果两个值都是布尔值true或都是布尔值false,则它们相等。
4·如果其中一个值是NaN,或者两个值都是NaN,则它们不相等。NaN和其他任何值都是不相等 的,包括它本身!通过x!==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式的值才为 true。
5·如果两个值为数字且数值相等,则它们相等。如果一个值为0,另一个值为-0,则它们同样相 等。
6·如果两个值为字符串,且所含的对应位上的16位数(参照3.2节)完全相等,则它们相等。如果 它们的长度或内容不同,则它们不等。两个字符串可能含义完全一样且所显示出的字符也一 样,但具有不同编码的16位值。JavaScript并不对Unicode进行标准化的转换,因此像这样的字 符串通过“===”和“==”运算符的比较结果也不相等。第三部分的String.localeCompare()提供了另 外一种比较字符串的方法。
7·如果两个引用值指向同一个对象、数组或函数,则它们是相等的。如果指向不同的对象,则它 们是不等的,尽管两个对象具有完全一样的属性。
相等运算符“==”和恒等运算符相似,但相等运算符的比较并不严格。如果两个操作数不是同一类型,那么相等运算符会尝试进行一些类型转换,然后进行比较:
1·如果两个操作数的类型相同,则和上文所述的严格相等的比较规则一样。如果严格相等,那 么比较结果为相等。如果它们不严格相等,则比较结果为不相等。
2·如果两个操作数类型不同,“==”相等操作符也可能会认为它们相等。检测相等将会遵守如下 规则和类型转换:
—如果一个值是null,另一个是undefined,则它们相等。
—如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值 进行比较。
—如果其中一个值是true,则将其转换为1再进行比较。如果其中一个值是false,则将 其转换为0再进行比较。
—如果一个值是对象,另一个值是数字或字符串,则使用3.8.3节所提到的转换规则将 对象转换为原始值,然后再进行比较。对象通过toString()方法或者valueOf()方法转 换为原始值。JavaScript语言核心的内置类首先尝试使用valueOf(),再尝试使用 toString(),除了日期类,日期类只使用toString()转换。那些不是JavaScript语言核心 中的对象则通过各自的实现中定义的方法转换为原始值。
—其他不同类型之间的比较均不相等。
这里有一个判断相等的小例子:
"1"==true
这个表达式的结果是true,这表明完全不同类型的值比较结果为相等。布尔值true首先转换为数字1,然后再执行比较。接下来,字符串“1”也转换为了数字1,因为两个数字的值相等,因此比较结果为true。
摘自:《JavaScript权威指南(第六版)》
收藏感谢收起
![](https://pic3.zhimg.com/760787b1b721788a80b1f839909b4f4e_xs.jpg)
收藏感谢
![](https://pic3.zhimg.com/v2-04973832e05bec5844559ba18bd7e5c0_xs.jpg)
来源:《你不知道的javascript》中卷
根源:ES5规范文档
“区别在于操作数类型不同时它们的处理方式不同”
对于不同的操作类型 它们的处理方式有哪些不同 请看文档
如es5 11.9.3.4-5 定义
1.如果Type(x)是数字 Type(y)是字符串 则返回x == ToNumber(y)的结果
2.如果Type(x)是字符串 Type(y)是数字 则返回 ToNumber(x) == y的结果
eg:
var a = 42;
var b = "42"
a === b ;//检查类型 类型不一致 不允许进行强制类型转换 所以为 false
a == b;//检查类型 类型不一致 Type(y) 为字符串 进行 ToNumber操作 "42"强制转换为42 再进行比较结果为 true
对于操作数为其他类型 比如操作数中有布尔值的 也有规范说明
先通读下规范吧 不要用想当然的运行处理逻辑来思考 人家都写着规范呢
书中对其他非常规 和 极端情况 都做了说明和总结
ps:非常规和极端情况 多数也是由规范引导的
收藏感谢
![](https://pic3.zhimg.com/v2-54c7f6313cee18ebc0a1f321a4502600_xs.jpg)
===即比较值 也比较类型
收藏感谢
![](https://pic1.zhimg.com/90/v2-0d38a5933ec0876c6f063e280ce16e67_250x0.jpg)
试听
刘看山知乎指南知乎协议应用工作
申请开通知乎机构号
侵权举报网上有害信息举报专区
违法和不良信息举报:010-82716601
儿童色情信息举报专区
联系我们 © 2018 知乎
Javascript 中 == 和 === 区别是什么?相关推荐
- 【前端工程师手册】说清楚JavaScript中的相等性判断
有哪些判断相等性的方法 JavaScript现在提供了三种方法来判断相等性: ===,三个等号即严格相等 ==,两个等号即宽松相等 Object.is(),ES6中用来判断相等的方法 判断相等性的细节 ...
- 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门)
by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门) (Why use stati ...
- JavaScript中的普通函数与构造函数比较
问题 什么是构造函数? 构造函数与普通函数区别是什么? 用new关键字的时候到底做了什么? 构造函数有返回值怎么办? 构造函数能当普通函数调用吗? this this永远指向当前正在被执行的函数或方法 ...
- 创建健壮的isArray()函数(JavaScript中判断对象类型的种种方法)
我们知道,JavaScript中检测对象类型的运算符有:typeof.instanceof,还有对象的constructor属性: 1) typeof 运算符 typeof 是一元运算符,返回结果是一 ...
- JavaScript中this关键字使用方法详解
在面向对象编程语言中,对于this关键字我们是非常熟悉的.比如C++.C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的.JavaScrip ...
- this调用语句必须是构造函数中的第一个可执行语句_谈谈JavaScript中的函数构造式和new关键字...
您是否曾困惑于 Javascript 中的new关键字呢?是否曾想理解关于 function 和 constructor 的区别是什么呢? 大多数 Javascript 的新开发者不太想要使用new关 ...
- 在JavaScript中逐个遍历数组?
如何使用JavaScript遍历数组中的所有条目? 我以为是这样的: forEach(instance in theArray) 其中theArray是我的数组,但这似乎是不正确的. #1楼 如果您不 ...
- crytojs加密 java解密,使用CryptoJS在Javascript中加密并在Java中解密
我试图使用谷歌的 https://code.google.com/p/crypto-js/#AES加密JavaScript,就像它的例子一样.问题是,我试图用Java解密它的结果是不同的.我可以看到的 ...
- JavaScript中window.open用法实例详解
本文较为详细的分析了JavaScript中window.open用法.分享给大家供大家参考.具体如下: 复制代码 代码如下: <script LANGUAGE="javascript& ...
最新文章
- CUDA上的量化深度学习模型的自动化优化
- 会议冲突!临时更新客户端!这些在线视频会议痛点统统解决掉!
- 【Linux 内核】实时调度类 ⑥ ( 实时调度类核心函数源码分析 | 插入进程到执行队列 | 从执行队列中选择优先级最高的进程 )
- 代表中国为世界做出探索,杭州城市大脑获IDC亚太区智慧城市大奖
- C# Aes CryptoStream Specified padding mode is not valid for this algorithm的解決方法
- 基于互联网大数据的管理创新
- jQuery mobile 之三
- python 网格线_Python版简单网格策略(教学)
- 第十三章 Perl的面向对象编程
- POJ 2226 二分图最小覆盖
- Spring中拦截/和拦截/*的区别
- verilog学习记(时序电路)
- chrome vue.js插件文档_前端开发者必备的40个VSCode插件!
- pytorch nonzero_[深度学习框架]PyTorch常用代码段
- 基于FPGA的cameralink编解码测试系统设计
- deepin系统引导_Deepin系统安装教程
- 《吉他自学三月通》学习指导
- Image Processing and Analysis_15_Image Registration:Image registration methods a survey——2003
- 基于STM32的智能抽油烟机系统
- 【go1.18】error obtaining VCS status: exit status
热门文章
- C++ P0002 旅行计划
- 就业歧视“花样翻新” 学者建议制定专门法律
- 饥荒暴食模式服务器无响应,饥荒暴食模式无银盘图文攻略介绍
- datagrid编辑单元格回车换行_Silverlight的DataGrid实现列标题和单元格换行
- 几个职位信息(阿里)
- Go语言之全局变量定义、函数内部局部变量定义和defer关键字和值类型与引用类型
- vue.js 三种方式安装
- Unity3d 周分享(15期 2019.4.14 )
- 奇偶性与魔术(二)——数学到魔术的初体验
- spring定时任务(Scheduled)运行阻塞不执行/Redission分布式锁阻塞问题