一个函数大于一个数组?

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)和falseIE9.对我来说,除了undefined没有办法说函数大于数组之外,没有这种比较的逻辑结果.

在ECMA脚本标准中读到它,它说>在对象上使用它的实际参数是在参数上调用ToNumber内部操作的结果.一些实验和进一步阅读告诉我,这与应用类型转换不同(Number) arg.阅读规范,我很难搞清楚这里发生了什么.

谁能让我知道这里发生了什么?

Esa*_*ija 60

在IE <9中,.toStringing (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没有),结果可能会有所不同,这并不奇怪.


Jiv*_*ngs 5

让我们深入了解ECMA规范.我已经包含了部分编号,因此您可以参考.

11.8.2大于运营商(>)

生产RelationalExpression:RelationalExpression> ShiftExpression的计算方法如下:

  1. 让lref成为评估RelationalExpression的结果.
  2. 设lval为GetValue(lref).
  3. 让rref成为评估ShiftExpression的结果.
  4. 设rval为GetValue(rref).
  5. 设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方法时,将执行以下步骤:

  1. 设O是调用ToObject传递此值作为参数的结果.
  2. 如果O是使用宿主对象(15.2.2.1)调用Object构造函数的结果,那么a.返回O或其他值,例如最初传递给构造函数的宿主对象.返回的特定结果是实现定义的.
  3. 返回O.