javascript中的1===[1]如何
How is 1 == [1] in javascript?
最近我在一次采访中被问到这个问题。
var a = 1;
var b = [1];
a == b;
将返回什么。
当我在chrome浏览器控制台上检查时,我得到了这个。
var a = 1;
var b = [1];
a == b;
true
我还检查了
var a = 1;
var b =(1);
a == b;
true
我知道b在大小为1的数组中。这是否意味着数组的大小被分配给了b。我真的很困惑。有人能给我解释一下其中的逻辑吗?
我并没有从Rayon的回答中真正理解valueOf
和toString
在将对象转换为基元值时是如何发挥作用的;所以我深入研究了ECMAScript 2015规范。
警告:答案很长。
我们要检查表达式1 == [1]
。
从12.10 Equality Operators开始,我们可以看到,在检索表达式值后,最后一步是
- 返回执行抽象相等比较的结果rval==lval
抽象相等比较在章节7.2.12抽象相等比较中定义。
7.2.12抽象平等比较
比较x==y,其中x和y是值,产生true或false。这样的比较如下:
- ReturnIfAbrupt(x)
- ReturnIfAbrupt(y)
- 如果类型(x)与类型(y)相同,则
a.返回严格相等比较的结果x===y- 如果x为null,y未定义,则返回true
- 如果x未定义,y为null,则返回true
- 如果Type(x)为Number,Type(y)为String,则返回比较结果x==ToNumber(y)
- 如果Type(x)为String,Type(y)为Number,则返回比较结果ToNumber(x)==y
- 如果Type(x)为Boolean,则返回比较结果ToNumber(x)==y
- 如果Type(y)为布尔值,则返回比较结果x==ToNumber(y)
- 如果Type(x)是String、Number或Symbol,而Type(y)是Object,则返回比较的结果x==ToPrimitive(y)
- 如果Type(x)是Object,Type(y)是String、Number或Symbol,则返回比较结果ToPrimitive(x)==y
- 返回false
表达式1 == [1]
属于情况10
因此,基本上,正如预期的那样,数组[1]
被转换为基元类型的值。
ToPrimitive在7.1.1 ToPrimitive(input[,PreferredType])中定义
抽象操作ToPrimitive接受一个输入参数和一个可选参数PreferredType。这个抽象操作ToPrimitive将其输入参数转换为非Object类型。
我还没有包括完整的报价,因为唯一有趣的对于这个例子,部分是:
- PreferredType参数(实际上是hintvar)从"default"(因为它没有传递)转换为"number"
- 使用相同的参数调用
OrdinaryToPrimitive
E现在是有趣的部分,OrdinaryToPrimitive执行以下操作:
- 断言:类型(O)为对象
- Assert:Type(hint)为String,其值为"String"或"number"
- 如果提示为"字符串",则
a.让methodNames为«"toString","valueOf"»- 否则,
a.让methodNames为«"valueOf","toString"»- 对于methodNames中的每个名称,按列表顺序执行
a.让方法为Get(O,name)
b.ReturnIfAbrupt(方法)
c.如果IsCallable(方法)为true,则
…i.设结果为Call(方法,O)
…ii。ReturnIfAbrupt(结果)
…iii.**如果Type(result)不是Object,则返回result。**- 引发TypeError异常
因此,为了将[1]
转换为基元值,运行时首先尝试调用valueOf
。此方法返回数组本身,数组本身是一个对象,因此5.c.ii接下来调用方法toString
此方法以逗号分隔的列表形式返回数组的元素,因此它只返回字符串"1"
。
因此,我们简化比较1 == "1"
,根据抽象等式比较的规则,第6点,意味着将"1"
转换为数字1
,而不是执行平凡比较1 = 1
。
请持怀疑态度的读者查看严格平等比较在标准中的实际定义。
你可以玩这种转换来更好地理解它们,这里是一个示例游乐场HTML文件
<html>
<head><title>title</title></head>
<body>
<script>
var old_valueOf = Array.prototype.valueOf;
var old_toString = Array.prototype.toString;
Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return old_valueOf.apply(this); };
Array.prototype.toString = function(){ console.log("Array::toString"); return old_toString.apply(this); };
console.log(1 == [1]); //Array::valueOf, Array::toString, true
Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return 2; };
console.log(1 == [1]); //Array::valueOf, false
Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return {}; };
Array.prototype.toString = function(){ console.log("Array::toString"); return {} };
console.log(1 == [1]); //Array::valueOf, Array::toString, Uncaught TypeError: Cannot convert object to primitive value
</script>
</body>
</html>
如果将对象与数字或字符串进行比较,JavaScript会尝试返回该对象的默认值。运算符尝试使用对象的
valueOf
和toString
方法将对象转换为基元值,即String
或Number
值。如果转换对象的尝试失败,则会生成运行时错误。【参考】
var a = 1;
var b = [1];
//What is happening when `(a==b)`
//typeof a; ==> number
//typeof b; ==>object
//Object is converted to Primitive using `valueOf` and `toString` methods of the objects
var val = b.valueOf().toString();
console.log('Values after conversion is: ' + val + ' And typeof converted value is: ' + typeof val);
//typeof val; ==> string
//a == b; will be evaluated as `true` because `'1' == 1` hence..
console.log(a == b); //'1'==1 ==> true
由于转换的值是String
类型,当比较number
和string
时,string
被转换为number
值,然后应用严格的比较
这是由于进行比较的类型。
在javascript中,可以使用==
或===
进行比较。在三重相等的情况下,这就是所谓的没有类型强制的相等,换句话说,这是一个严格的比较。
类型强制的平等
相反,这意味着使用双等于操作数是带有类型强制的等于。
这意味着什么
简单地说,这意味着javascript将使用内置方法将值转换为基元类型,以便进行比较。具体地,这些方法是.valueOf()
和.toString()
。
以下是一些例子:
0 == false // true, auto type coercion
0 === false // false, because they are of a different type
1 == "1" // true, auto type coercion
1 === "1" // false, because they are of a different type
Ergo:
1 == [1] // true
1 === [1] // false, because they are of a different type
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用WCF服务和javascript表单post上传.doc文件
- 如何通过ajax刷新JSF填充的javascript变量
- 如何使Javascript动态html表及其上的事件
- Javascript-如何读取json文件中的列并将其保存在Javascript数组中
- 如何使用javascript或html下载PDF格式的填写表单
- 如何使用javascript从主svg对象动态创建svg视图框
- 播放当前视频时如何停止其他视频?JavaScript
- 如何将输入(type=text)从html表单传递到javascript函数
- 如何使用json将对象列表从java转换为javascript
- 如何调用这个匿名 JavaScript 函数
- 我应该如何从xml文件构建一个javascript页面
- 如何包含特定于每个视图angularjs的javascript文件
- Chrome开发工具(如何知道我在调用哪个javascript对象)
- 如何确定javascript已经完成了某些操作.ios上的
- 如何javascript验证<输入类型=文件多个>如果浏览器不支持多个
- 如何javascript调用iframe加载的文件函数
- 事件如何(JavaScript代码)的全日历多天跨度
- 如何javascript获得操作系统语言在Chrome.不是浏览器的语言.(导航器.语言是浏览器语言!)
- 如何javascript正则表达式匹配以下内容