hma*_*ary 38 javascript arrays coercion
最近我在接受采访时被问到这个问题.
var a = 1;
var b = [1];
Run Code Online (Sandbox Code Playgroud)
什么会a == b;回来.
当我在我的Chrome浏览器控制台上检查时,我得到了这个.
var a = 1;
var b = [1];
a == b;
true
Run Code Online (Sandbox Code Playgroud)
我也检查过了
var a = 1;
var b =(1);
a == b;
true
Run Code Online (Sandbox Code Playgroud)
我知道b在大小为1的数组中.这是否意味着数组的大小被分配给b.我真的很困惑.任何人都可以解释我的逻辑吗?
Ray*_*yon 51
如果将对象与数字或字符串进行比较,JavaScript会尝试返回该对象的默认值.运算符尝试使用对象的和方法将对象转换为原始值,
String或Number值.如果转换对象的尝试失败,则会生成运行时错误.[ 参考 ]valueOftoString
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 ==> trueRun Code Online (Sandbox Code Playgroud)
由于转换后的值属于类型String,因此在比较a number和a时string,会将其string转换为number值,然后应用严格比较.
Mar*_*oom 51
我没有真正了解Rayon 在将对象转换为原始值时如何解释valueOf并toString发挥作用; 所以我深入研究了ECMAScript 2015规范.
警告:答案很长.
我们想检查表达式1 == [1].
从12.10 Equality Operators开始,我们看到,在检索表达式值之后,最后一步是
- 返回执行抽象等式比较rval == lval的结果
抽象平等比较在第7.2.12章抽象平等比较中定义.
7.2.12抽象等式比较
比较x == y,其中x和y是值,产生真或假.这样的比较如下进行:
- ReturnIfAbrupt(X).
- ReturnIfAbrupt(Y).
- 如果Type(x)与Type(y)相同,那么
a.返回执行Strict Equality Comparison 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)是布尔值,则返回比较结果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类型.
我没有包括完整的引用,因为唯一有趣的,对于这个例子,部分是:
OrdinaryToPrimitive 用相同的参数调用.E现在是有趣的部分,OrdinaryToPrimitive执行以下操作:
- 断言:类型(O)是对象
- 断言:Type(提示)是String,其值为"string"或"number".
- 如果提示是"字符串",那么
a.让methodNames为«"toString","valueOf"».- 否则,
a.让methodNames为«"valueOf","toString"».- 对于List顺序中methodNames中的每个名称,执行
a.让方法为Get(O,name).
湾 ReturnIfAbrupt(方法).
C.如果IsCallable(方法)为真,那么
...... i.让结果为Call(方法,O).
...... ii.ReturnIfAbrupt(结果).
...... iii.**如果Type(result)不是Object,则返回结果.**- 抛出TypeError异常
因此,为了转换[1]为原始值,运行时首先尝试调用valueOf.此方法返回数组本身,这是一个对象,因此通过5.c.iiitoString接下来调用该方法.
此方法以逗号分隔列表的形式返回数组的元素,因此它只返回字符串"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>
Run Code Online (Sandbox Code Playgroud)
gdg*_*dgr 13
这是由于进行了比较的类型.
在javascript中,可以使用其中一个==或===进行比较.在三等于的情况下,这就是所谓的没有类型强制的平等,换句话说,它是一种严格的比较.
与类型强制相等
相反,这意味着使用double equals操作数与类型强制相等.
这是什么意思?
简单地说,这意味着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
Run Code Online (Sandbox Code Playgroud)
人机工程学:
1 == [1] // true
1 === [1] // false, because they are of a different type
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4209 次 |
| 最近记录: |