<分区>
最近我在面试中被问到这个问题。
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。我真的很困惑。谁能给我解释一下逻辑?
<分区>
最近我在面试中被问到这个问题。
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 相等运算符开始,我们看到,在检索表达式值之后,最后一步是
- Return the result of performing Abstract Equality Comparison rval == lval
抽象平等比较在7.2.12 抽象平等比较一章中定义。
7.2.12 Abstract Equality Comparison
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
- ReturnIfAbrupt(x).
- ReturnIfAbrupt(y).
- If Type(x) is the same as Type(y), then
a. Return the result of performing Strict Equality Comparison x === y.- If x is null and y is undefined, return true.
- If x is undefined and y is null, return true.
- If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
- If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
- If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
- If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
- If Type(x) is either String, Number, or Symbol and Type(y) is Object, then return the result of the comparison x == ToPrimitive(y).
- If Type(x) is Object and Type(y) is either String, Number, or Symbol, then return the result of the comparison ToPrimitive(x) == y.
- Return false.
表达式 1 == [1]
属于情况 10。
所以基本上,正如预期的那样,数组 [1]
被转换为基本类型的值。
ToPrimitive 定义在 7.1.1 ToPrimitive ( input [, PreferredType] )
The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type.
我没有包含完整的引文,因为对于这个例子,唯一有趣的部分是:
OrdinaryToPrimitive
使用相同的参数调用。现在是有趣的部分,OrdinaryToPrimitive 执行以下操作:
- Assert: Type(O) is Object
- Assert: Type(hint) is String and its value is either "string" or "number".
- If hint is "string", then
a. Let methodNames be «"toString", "valueOf"».- Else,
a. Let methodNames be «"valueOf", "toString"».- For each name in methodNames in List order, do
a. Let method be Get(O, name).
b. ReturnIfAbrupt(method).
c. If IsCallable(method) is true, then
... i. Let result be Call(method, O).
... ii. ReturnIfAbrupt(result).
... iii. **If Type(result) is not Object, return result. **- Throw a TypeError exception
因此,为了将 [1]
转换为原始值,运行时首先尝试调用 valueOf
。此方法返回数组本身,它是一个对象,因此 5.c.iii 接下来调用方法 toString
。
此方法以逗号分隔的列表形式返回数组的元素,因此它仅返回字符串 "1"
。
所以我们减少了比较1 == "1"
,根据抽象相等比较的规则,第 6 点,意味着转换 "1"
转换为数字 1
,然后执行简单的比较 1 = 1
。
邀请可疑的读者检查标准中实际上如何定义严格相等比较。
您可以尝试这种转换以更好地理解它们,这里是一个示例 playground 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 - javascript 中的 1 == [1] 是怎样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37021335/