evi*_*bag 43 javascript arrays comparison function ecmascript-5
我的一个朋友在一些Javascript代码中发现了一些有趣的行为,我决定进一步调查.
比较
(function (x) {return x*x;}) > [1,2,3]
Run Code Online (Sandbox Code Playgroud)
返回true
大多数主流浏览器(Firefox,Chrome,Opera和Safari)和false
IE9.对我来说,除了undefined
没有办法说函数大于数组之外,没有这种比较的逻辑结果.
在ECMA脚本标准中读到它,它说>
在对象上使用它的实际参数是在参数上调用ToNumber内部操作的结果.一些实验和进一步阅读告诉我,这与应用类型转换不同(Number) arg
.阅读规范,我很难搞清楚这里发生了什么.
谁能让我知道这里发生了什么?
Esa*_*ija 60
在IE <9中,.toString
ing (function (x) {return x*x;})
给出了
"(function (x) {return x*x;})"
Run Code Online (Sandbox Code Playgroud)
在chrome中它给出:
"function (x) {return x*x;}"
Run Code Online (Sandbox Code Playgroud)
如果你比较:
"function (x) {return x*x;}" > "1,2,3" // true
"(function (x) {return x*x;})" > "1,2,3" // false
Run Code Online (Sandbox Code Playgroud)
这与比较实际上是一样的:
"f" > "1"
"(" > "1"
Run Code Online (Sandbox Code Playgroud)
这与比较相同:
102 > 49
40 > 49
Run Code Online (Sandbox Code Playgroud)
这就是我们从函数和数组比较到简单数字比较的方法:)
T.J*_*der 54
操作数>
不一定转换为数字.该抽象关系比较算法要求ToPrimitive
与提示 Number
,但ToPrimitive
仍然可以返回一个字符串(在两者的功能和数组的情况下,它).
所以你最终比较两个字符串.调用toString
函数对象的结果不是由规范定义的,尽管大多数主要引擎返回函数的源代码(或其某种形式,格式不同).调用toString
数组的结果与join
.
所以你很可能最终会这样做:
"function (x) {return x*x;}" > "1,2,3"
Run Code Online (Sandbox Code Playgroud)
由于该功能的字符串的确切形式可能因浏览器而异(并且注意到Esailija的调查 - 看起来IE9保持外部()
,但Chrome没有),结果可能会有所不同,这并不奇怪.
让我们深入了解ECMA规范.我已经包含了部分编号,因此您可以参考.
11.8.2大于运营商(>)
生产RelationalExpression:RelationalExpression> ShiftExpression的计算方法如下:
- 让lref成为评估RelationalExpression的结果.
- 设lval为GetValue(lref).
- 让rref成为评估ShiftExpression的结果.
- 设rval为GetValue(rref).
- 设r是执行抽象关系比较 rval <lval,LeftFirst等于false的结果.(见11.8.5).
其中重要的部分是抽象关系比较.定义如下:
11.8.5抽象关系比较算法
toPrimitive
首先在对象上调用该函数.虽然如果可以的话,这会偏向于返回Numbers,但也可以派生字符串.一旦发生这种情况,将检查以下内容:
一个.如果py是px的前缀,则返回false.(如果q可以是连接p和其他一些String r的结果,则字符串值p是字符串值q的前缀.请注意,任何String都是其自身的前缀,因为r可能是空字符串.)
湾 如果px是py的前缀,则返回true.
C.设k是最小的非负整数,使得px内位置k处的字符与py内位置k处的字符不同.(必须有这样的ak,因为String都不是另一个的前缀.)
d.设m是整数,它是px内位置k处字符的代码单位值.即 设n是整数,它是py内位置k处的字符的代码单元值.F.如果m <n,则返回true.否则,返回false.
这意味着将检查String中与第一个字符不同的第一个字符.正如Esailija所指出的,IE的toString()
函数返回的字符串与其他浏览器的字符串稍有不同,导致发生了不同的比较.
浏览器之间的这种差异似乎是有效的,如下所述:
15.2.4.4 Object.prototype.valueOf()
调用valueOf方法时,将执行以下步骤:
- 设O是调用ToObject传递此值作为参数的结果.
- 如果O是使用宿主对象(15.2.2.1)调用Object构造函数的结果,那么a.返回O或其他值,例如最初传递给构造函数的宿主对象.返回的特定结果是实现定义的.
- 返回O.