我正在使用JSLint来检查 JavaScript,并且在执行诸如在语句内部进行比较之类的操作时,它会返回许多建议以将==
(两个等号)替换为===
(三个等号)。idSele_UNVEHtype.value.length == 0
if
有没有性能优势,以代替==
用===
?
由于存在许多比较运算符,因此任何性能改进都会受到欢迎。
如果不发生类型转换,性能会不会比==
?
我正在使用JSLint来检查 JavaScript,并且在执行诸如在语句内部进行比较之类的操作时,它会返回许多建议以将==
(两个等号)替换为===
(三个等号)。idSele_UNVEHtype.value.length == 0
if
有没有性能优势,以代替==
用===
?
由于存在许多比较运算符,因此任何性能改进都会受到欢迎。
如果不发生类型转换,性能会不会比==
?
除了不进行类型转换之外,严格相等运算符 ( ===
) 的行为与抽象相等运算符 ( ==
) 相同,并且类型必须相同才能被视为相等。
该==
运营商将比较平等做任何必要的类型转换之后。该===
运营商将不会进行转换,因此,如果两个值是不一样的类型===
将简单地返回false
。两者都一样快。
引用 Douglas Crockford 出色的JavaScript: The Good Parts,
JavaScript 有两组相等运算符:
===
and!==
,以及它们的邪恶双胞胎==
and!=
。好的方法会按照您期望的方式工作。如果两个操作数的类型和值相同,则===
产生true
和!==
产生false
。当操作数是相同类型时,邪恶双胞胎会做正确的事情,但如果它们是不同类型,它们会尝试强制转换值。他们这样做的规则既复杂又难以记住。这些是一些有趣的案例:'' == '0' // false 0 == '' // true 0 == '0' // true false == 'false' // false false == '0' // true false == undefined // false false == null // false null == undefined // true ' \t\r\n ' == 0 // true
缺乏传递性令人担忧。我的建议是永远不要使用邪恶的双胞胎。相反,请始终使用
===
和!==
。刚刚显示的所有比较都false
与===
操作员进行了比较。
@Casebash在评论和@Phillipe Laybaert 关于对象的回答中提出了一个好观点。对于对象,==
并===
彼此一致地行动(除非在特殊情况下)。
var a = [1,2,3];
var b = [1,2,3];
var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };
var e = "text";
var f = "te" + "xt";
a == b // false
a === b // false
c == d // false
c === d // false
e == f // true
e === f // true
特殊情况是当您将一个基元与一个评估为相同基元的对象进行比较时,由于其toString
或valueOf
方法。例如,考虑将字符串原语与使用String
构造函数创建的字符串对象进行比较。
"abc" == new String("abc") // true
"abc" === new String("abc") // false
此处==
操作符正在检查两个对象的值并返回true
,但===
看到它们的类型不同并返回false
。哪一个是正确的?这实际上取决于您要比较的内容。我的建议是完全绕过这个问题,只是不要使用String
构造函数从字符串文字创建字符串对象。
参考
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
使用==
运算符 ( Equality )
true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2; //true, because "2" is converted to 2 and then compared
使用===
运算符 ( Identity )
true === 1; //false
"2" === 2; //false
这是因为相等运算符==
确实输入了强制类型,这意味着解释器会在比较之前隐式地尝试转换值。
另一方面,身份运算符===
不执行类型强制,因此在比较时不转换值,因此跳过一个步骤会更快(根据This JS benchmark test)。
这是==
和之间的相等比较的有趣可视化===
。
来源:https : //github.com/dorey/JavaScript-Equality-Table(演示,统一演示)
var1 === var2
当使用===
JavaScript的平等的测试,一切都是原样。
在评估之前没有任何东西被转换。
var1 == var2
当==
用于 JavaScript 相等性测试时,会发生一些奇怪的转换。
除非你完全了解了时髦的转换所发生的与==
,始终使用===
。
在这里的答案中,我没有读到任何关于平等意味着什么的内容。有人会说这===
意味着相等和相同类型,但事实并非如此。它实际上意味着两个操作数都引用同一个 object,或者在值类型的情况下,具有相同的 value。
因此,让我们使用以下代码:
var a = [1,2,3];
var b = [1,2,3];
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
和这里一样:
var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
甚至:
var a = { };
var b = { };
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
这种行为并不总是很明显。这个故事不仅仅是平等和同一类型。
规则是:
对于值类型(数字):
a === b
如果a
和b
具有相同的值并且属于相同类型,则返回 true
对于引用类型:
a === b
如果a
并b
引用完全相同的对象,则返回 true
对于字符串:
a === b
如果a
和b
都是字符串并且包含完全相同的字符,则返回 true
字符串不是值类型,但在 Javascript 中它们的行为类似于值类型,因此当字符串中的字符相同且长度相同时,它们将“相等”(如第三条规则所述)
现在变得有趣了:
var a = "12" + "3";
var b = "123";
alert(a === b); // returns true, because strings behave like value types
但是这个怎么样?:
var a = new String("123");
var b = "123";
alert(a === b); // returns false !! (but they are equal and of the same type)
我认为字符串的行为类似于值类型?嗯,这取决于你问谁......在这种情况下,a 和 b 不是同一类型。a
是 类型Object
,而b
是 类型string
。请记住,使用String
构造函数创建字符串对象会创建大多数情况下Object
表现为字符串的类型。
让我补充一下这个忠告:
如有疑问,请阅读规范!
ECMA-262 是一种脚本语言的规范,JavaScript 是其方言。当然,在实践中,最重要的浏览器的行为方式比对某些事情应该如何处理的深奥定义更重要。但是理解为什么new String("a") !== "a"是有帮助的。
请让我解释如何阅读规范以澄清这个问题。我看到在这个非常古老的话题中,没有人对非常奇怪的效果有答案。所以,如果你能阅读规范,这将对你的职业有很大帮助。这是一种后天的技能。所以,让我们继续。
在 PDF 文件中搜索 === 将我带到规范的第 56 页:11.9.4。严格等于运算符 ( === ),在仔细阅读规范后,我发现:
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) 不是 Number,则转到步骤 11。
5. 如果 x 是NaN,则返回false。
6. 如果 y 是NaN,则返回false。
7. 如果 x 与 y 的数值相同,则返回true。
8. 如果 x 是 +0 并且 y 是 -0,则返回true。
9. 如果 x 是 -0 并且 y 是 +0,则返回true。
10. 返回false。
11.如果Type(x)是String,那么如果x和y是完全相同的字符序列(长度相同,对应位置的字符相同),则返回true;否则,返回false。
12. 如果 Type(x) 是布尔值,如果 x 和 y 都为真或都为假,则返回真;否则,返回false。 13.返回真
如果 x 和 y 指的是同一个对象,或者如果它们指的是相互连接的对象(见 13.1.2)。否则,返回false。
有趣的是第 11 步。是的,字符串被视为值类型。但这并不能解释为什么new String("a") !== "a"。我们是否有不符合 ECMA-262 的浏览器?
没那么快!
让我们检查操作数的类型。将它们包装在typeof() 中,亲自尝试一下。我发现new String("a")是一个对象,并且使用了第 1 步:如果类型不同,则返回false。
如果您想知道为什么new String("a")不返回字符串,那么来做一些阅读规范的练习怎么样?玩得开心!
Aidiakapi 在下面的评论中写道:
从规范
11.2.2 新运营商:
如果 Type(constructor) 不是 Object,则抛出 TypeError 异常。
换句话说,如果 String 不是 Object 类型,它就不能与 new 运算符一起使用。
new总是返回一个对象,即使对于String构造函数也是如此。唉!字符串的值语义(参见步骤 11)丢失了。
这最终意味着:new String("a") !== "a"。