一个函数比一个数组大?
我的一个朋友在一些Javascript代码中发现了一些有趣的行为,我决定进一步调查。
比较
(function (x) {return x*x;}) > [1,2,3]
在大多数主stream浏览器(Firefox,Chrome,Opera和Safari)中返回true
,在IE9中返回false
。 对我来说,这个比较没有任何逻辑结果,因为没有办法说函数大于数组。
在ECMA脚本标准中读到这一点,它说在对象上使用时的实际参数是对参数调用ToNumber内部操作的结果。 一些实验和进一步的阅读告诉我,这与应用(Number) arg
类的types转换不同。 阅读规范,我很难弄清楚这里发生了什么。
任何人都可以填写我在这里发生了什么?
操作数>
不一定转换为数字。 抽象关系比较algorithm使用提示 Number
调用ToPrimitive
,但ToPrimitive
仍然可以返回一个string(在函数和数组的情况下)。
所以你最终比较两个string。 对函数对象调用toString
的结果并不是由spec定义的,尽pipe大多数主要的引擎都返回了函数的源代码(或者某种forms的,格式不同)。 在数组上调用toString
的结果与join
相同。
所以可能性基本上是这样的:
"function (x) {return x*x;}" > "1,2,3"
由于函数string的确切forms可能因浏览器到浏览器而异(并注意Esailija的调查 – 看起来像IE9保持外()
,铬没有),结果可能会有所不同。
在IE <9中.toString
ing (function (x) {return x*x;})
给出
"(function (x) {return x*x;})"
而在铬它给:
"function (x) {return x*x;}"
如果你比较:
"function (x) {return x*x;}" > "1,2,3" // true "(function (x) {return x*x;})" > "1,2,3" // false
这与比较实际上是一样的:
"f" > "1" "(" > "1"
这与比较相同:
102 > 49 40 > 49
所以这就是我们如何从一个函数和数组比较到一个简单的数字比较:)
让我们来深入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抽象关系比较algorithm
toPrimitive
函数将首先在对象上被调用。 虽然这是有偏见的返回数字,如果可以的话,string也可以派生。 一旦发生这种情况,将检查以下内容:
一个。 如果py是px的前缀,则返回false。 (string值p是string值q的前缀,如果q可以是连接p和其他stringr的结果,请注意任何string都是它自己的前缀,因为r可能是空string。
湾 如果px是py的前缀,则返回true。
C。 令k是最小的非负整数,使得px内位置k上的字符与py内位置k上的字符不同 。 (必须有这样的一个string,因为这两个string都不是另一个的前缀。)
d。 设m为px内位置k处字符的代码单元值的整数。 即 设n是py中位置k上的字符的代码单元值的整数。 F。 如果m <n,则返回true。 否则,返回false。
这意味着将检查string中与第一个字符不同的第一个字符。 正如Esailija指出的那样,IE的toString()
函数返回的string与其他浏览器略有不同,导致了不同的比较。
浏览器之间的这种差异似乎是有效的,如下所述:
15.2.4.4 Object.prototype.valueOf()
当调用valueOf方法时,将采取以下步骤:
- 设O是调用ToObject传递该值作为参数的结果。
- 如果O是使用主机对象(15.2.2.1)调用Object构造函数的结果,那么a。 返回O或其他值,例如最初传递给构造函数的主机对象。 返回的具体结果是实现定义的。
- 返回O.
IE和其他浏览器都将使用相同的string比较这两个对象。 不同的原因是IE会将函数转换为input的文字string:
(function (x) {return x*x;})
其他浏览器(在Firefox上testing)将输出它自己编译的函数解释:
function (x) { return x * x; }
由于IE函数表示的第一个字符是(
大于1
,所以返回false,由于f
低于1
,所以其他浏览器会返回true。