简体   繁体   English

一个函数大于一个数组?

[英]A function is larger than an array?

A friend of mine discovered some interesting behaviour in some Javascript code, which I decided to investigate further. 我的一个朋友在一些Javascript代码中发现了一些有趣的行为,我决定进一步调查。

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. 在大多数主流浏览器(Firefox,Chrome,Opera和Safari)中返回true ,在IE9中返回false 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. 对我来说,除了undefined之外undefined这种比较的逻辑结果,因为没有办法说函数大于数组。

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. 在ECMA脚本标准中读到这一点,它表示>在对象上使用它时的实际参数是在参数上调用ToNumber内部操作的结果。 Some experiments and further reading tells me that this is not the same as applying a type conversion such as (Number) arg . 一些实验和进一步阅读告诉我,这与应用类型转换(如(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? 谁能让我知道这里发生了什么?

In IE<9, .toString ing (function (x) {return x*x;}) gives 在IE <9中, .toString ing (function (x) {return x*x;})给出

"(function (x) {return x*x;})" 

While in chrome it gives: 在chrome中它给出:

"function (x) {return x*x;}"

If you compare: 如果你比较:

"function (x) {return x*x;}" > "1,2,3" // true
"(function (x) {return x*x;})"  > "1,2,3"  // false

Which is effectively the same as comparing: 这与比较实际上是一样的:

"f" > "1"
"(" > "1"

Which is the same as comparing: 这与比较相同:

102 > 49
40 > 49

So that's how we get from a function and array comparison to a simple number comparison :) 这就是我们从函数和数组比较到简单数字比较的方法:)

The operands to > are not necessarily converted to numbers. >的操作数不一定转换为数字。 The abstract relational comparison algorithm calls ToPrimitive with the hint Number , but ToPrimitive may still return a string (and in the case of both functions and arrays, it does). 抽象关系比较算法使用提示 Number调用ToPrimitive ,但ToPrimitive仍然可以返回一个字符串(在函数和数组的情况下,它都会返回)。

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). 虽然大多数主要引擎都返回函数的源代码(或者它的某种形式,并且格式不同),但是在规范中没有定义在函数对象上调用toString的结果。 The result of calling toString on arrays is the same as join . 在数组上调用toString的结果与join相同。

So the odds are that you'll end up basically doing this: 所以你很可能最终会这样做:

"function (x) {return x*x;}" > "1,2,3"

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. 由于该功能的字符串的确切形式可能因浏览器而异(并注意到Esailija的调查 - 看起来IE9保持外部() ,但Chrome没有),结果可能会有所不同,这并不奇怪。

Let's dive into the ECMA Specification. 让我们深入了解ECMA规范。 I've included the section numbers so you can reference. 我已经包含了部分编号,因此您可以参考。

11.8.2 The Greater-than Operator ( > ) 11.8.2大于运营商(>)

The production RelationalExpression : RelationalExpression > ShiftExpression is evaluated as follows: 生产RelationalExpression:RelationalExpression> ShiftExpression的计算方法如下:

  1. Let lref be the result of evaluating RelationalExpression. 让lref成为评估RelationalExpression的结果。
  2. Let lval be GetValue(lref). 设lval为GetValue(lref)。
  3. Let rref be the result of evaluating ShiftExpression. 让rref成为评估ShiftExpression的结果。
  4. Let rval be GetValue(rref) . 设rval为GetValue(rref)。
  5. Let r be the result of performing abstract relational comparison rval < lval with LeftFirst equal to false. 设r是执行抽象关系比较 rval <lval,LeftFirst等于false的结果。 (see 11.8.5). (见11.8.5)。

The important part of that is the Abstract Relational Comparison . 其中重要的部分是抽象关系比较 Which is defined: 定义如下:

11.8.5 The Abstract Relational Comparison Algorithm 11.8.5抽象关系比较算法

The toPrimitive function will first be called on the Objects. 首先在Objects上调用toPrimitive函数。 Although this is biased to return Numbers if it can, Strings can also be derived. 虽然如果可以的话,这会偏向于返回Numbers,但也可以派生字符串。 Once this has occurred, the following will be examined: 一旦发生这种情况,将检查以下内容:

a. 一个。 If py is a prefix of px, return false. 如果py是px的前缀,则返回false。 (A String value p is a prefix of String value q if q can be the result of concatenating p and some other String r. Note that any String is a prefix of itself, because r may be the empty String.) (如果q可以是连接p和其他一些String r的结果,则字符串值p是字符串值q的前缀。请注意,任何String都是其自身的前缀,因为r可能是空字符串。)

b. If px is a prefix of py, return true. 如果px是py的前缀,则返回true。

c. C。 Let k be the smallest nonnegative integer such that the character at position k within px is different from the character at position k within py . 设k是最小的非负整数,使得px内位置k处的字符与py内位置k处的字符不同 (There must be such ak, for neither String is a prefix of the other.) (必须有这样的ak,因为String都不是另一个的前缀。)

d. d。 Let m be the integer that is the code unit value for the character at position k within px. 设m是整数,它是px内位置k处字符的代码单位值。 e. Let n be the integer that is the code unit value for the character at position k within py. 设n是整数,它是py内位置k处的字符的代码单元值。 f. F。 If m < n, return true. 如果m <n,则返回true。 Otherwise, return false. 否则,返回false。

This means that the first character in the String that is different than the other will be examined. 这意味着将检查String中与第一个字符不同的第一个字符。 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. 正如Esailija所指出的,IE的toString()函数返回的字符串与其他浏览器的字符串略有不同,导致发生了不同的比较。

This difference between the browsers appears to be valid as is stated here: 浏览器之间的这种差异似乎是有效的,如下所述:

15.2.4.4 Object.prototype.valueOf ( ) 15.2.4.4 Object.prototype.valueOf()

When the valueOf method is called, the following steps are taken: 调用valueOf方法时,将执行以下步骤:

  1. Let O be the result of calling ToObject passing the this value as the argument. 设O是调用ToObject传递此值作为参数的结果。
  2. If O is the result of calling the Object constructor with a host object (15.2.2.1), then a. 如果O是使用宿主对象(15.2.2.1)调用Object构造函数的结果,那么a。 Return either O or another value such as the host object originally passed to the constructor. 返回O或其他值,例如最初传递给构造函数的宿主对象。 The specific result that is returned is implementation-defined. 返回的特定结果是实现定义的。
  3. Return O. 返回O.

Both IE and other browsers will use the same string comparison for both objects. IE和其他浏览器都将对两个对象使用相同的字符串比较。 The reason for the difference is IE will convert the function into the literal string as entered: 产生差异的原因是IE会将函数转换为输入的文字字符串:

(function (x) {return x*x;})

Other browsers (testing on Firefox) will output its own compiled interpretation of the function: 其他浏览器(在Firefox上测试)将输出自己编译的函数解释:

function (x) {
    return x * x;
}

Since the first character of IE's function representation is ( , which is higher than 1 , it will return false. Since f is lower then 1 , other browsers will return true. 由于IE的函数表示的第一个字符是( ,它高于1 ,它将返回false。由于f低于1 ,其他浏览器将返回true。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM