函数比数组大?
我的一位朋友在一些 Javascript 代码中发现了一些有趣的行为,我决定对其进行进一步研究。
该比较
(function (x) {return x*x;}) > [1,2,3]
在大多数主要浏览器(Firefox、Chrome、Opera 和 Safari)中返回 true
,在 IE9 中返回 false
。对我来说,除了 undefined
之外,这种比较没有任何逻辑结果,因为无法说函数大于数组。
在 ECMA 脚本标准中阅读这一点,它说当 >
用于对象时,它的实际参数是对参数调用 ToNumber 内部操作的结果。一些实验和进一步的阅读告诉我,这与应用类型转换(例如 (Number) arg
)不同。阅读规范后,我很难弄清楚这里发生了什么。
谁能告诉我这里到底发生了什么?
A friend of mine discovered some interesting behaviour in some Javascript code, which I decided to investigate further.
The comparison
(function (x) {return x*x;}) > [1,2,3]
returns true
in most major browsers (Firefox, Chrome, Opera and Safari) and false
in IE9. To me, there is no logical result of this comparison other than undefined
as there is no way to say that a function is greater than an array.
Reading up on this in the ECMA-script standard, it says that the actual arguments of >
when it is used on objects are the result of calling the ToNumber internal operation on the arguments. Some experiments and further reading tells me that this is not the same as applying a type conversion such as (Number) arg
. Reading the specification, I have a hard time figuring out what's going on here.
Can anyone fill me in on what's really happening here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 IE<9 中,
.toString
ing(function (x) {return x*x;})
给出While 在 chrome 中它给出:
如果你比较:
这实际上是与比较相同:
与比较相同:
这就是我们从函数和数组比较到简单数字比较的方式:)
In IE<9,
.toString
ing(function (x) {return x*x;})
givesWhile in chrome it gives:
If you compare:
Which is effectively the same as comparing:
Which is the same as comparing:
So that's how we get from a function and array comparison to a simple number comparison :)
>
的操作数不一定转换为数字。 抽象关系比较算法使用 调用ToPrimitive
提示Number
,但ToPrimitive
仍可能返回一个字符串(对于函数和数组,它确实如此)。所以你最终会比较两个字符串。在函数对象上调用
toString
的结果不是由规范定义,尽管大多数主要引擎返回函数的源代码(或其某种形式,并且格式各不相同)。在数组上调用toString
的结果是相同的作为加入
。因此,您最终基本上会这样做的可能性是:
由于该函数的字符串的确切形式可能因浏览器而异(并注意 Esailija 的调查 ——看起来 IE9 保留了外部
()
,Chrome 没有),结果可能并不令人意外 各不相同。The operands to
>
are not necessarily converted to numbers. The abstract relational comparison algorithm callsToPrimitive
with the hintNumber
, butToPrimitive
may still return a string (and in the case of both functions and arrays, it does).So you end up comparing two strings. The result of calling
toString
on function objects is not defined by the spec, although most major engines return the source code of the function (or some form of it, and the formatting varies). The result of callingtoString
on arrays is the same asjoin
.So the odds are that you'll end up basically doing this:
Since the exact form of the string for the function may vary from browser-to-browser (and note Esailija's investigations — looks like IE9 keeps the outer
()
, Chrome doesn't), it's not too surprising that the result may vary.让我们深入了解 ECMA 规范。我已经包含了部分编号,以便您可以参考。
11.8.2 大于运算符 ( > )
其中重要的部分是抽象关系比较。其定义为:
11.8.5 抽象关系比较算法
首先将在对象上调用
toPrimitive
函数。虽然如果可以的话,这偏向于返回数字,但也可以派生字符串。一旦发生这种情况,将检查以下内容:这意味着将检查字符串中与其他字符不同的第一个字符。正如 Esailija 所指出的,IE 的 toString() 函数返回的字符串与其他浏览器的字符串略有不同,从而导致发生不同的比较。
浏览器之间的这种差异似乎是有效的,如下所述:
15.2.4.4 Object.prototype.valueOf ( )
Let's dive into the ECMA Specification. I've included the section numbers so you can reference.
11.8.2 The Greater-than Operator ( > )
The important part of that is the Abstract Relational Comparison. Which is defined:
11.8.5 The Abstract Relational Comparison Algorithm
The
toPrimitive
function will first be called on the Objects. Although this is biased to return Numbers if it can, Strings can also be derived. Once this has occurred, the following will be examined:This means that the first character in the String that is different than the other will be examined. As it has been pointed out by Esailija, IE's
toString()
function returns a slightly different String to that of the other browsers, resulting in a different comparison taking place.This difference between the browsers appears to be valid as is stated here:
15.2.4.4 Object.prototype.valueOf ( )
IE 和其他浏览器都会对这两个对象使用相同的字符串比较。差异的原因是 IE 会将函数转换为输入的文字字符串:
其他浏览器(在 Firefox 上测试)将输出其自己编译的函数解释:
由于 IE 函数表示的第一个字符是
( 高于
1
时,将返回 false,因为f
低于1
,其他浏览器将返回 true。Both IE and other browsers will use the same string comparison for both objects. The reason for the difference is IE will convert the function into the literal string as entered:
Other browsers (testing on Firefox) will output its own compiled interpretation of the function:
Since the first character of IE's function representation is
(
, which is higher than1
, it will return false. Sincef
is lower then1
, other browsers will return true.