函数比数组大?

发布于 2025-01-08 06:34:51 字数 479 浏览 0 评论 0原文

我的一位朋友在一些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感情洁癖 2025-01-15 06:34:51

在 IE<9 中, .toStringing (function (x) {return x*x;}) 给出

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

While 在 chrome 中它给出:

"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

这就是我们从函数和数组比较到简单数字比较的方式:)

In IE<9, .toStringing (function (x) {return x*x;}) gives

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

While in chrome it gives:

"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 :)

山有枢 2025-01-15 06:34:51

> 的操作数不一定转换为数字。 抽象关系比较算法使用 调用 ToPrimitive提示 Number,但 ToPrimitive 仍可能返回一个字符串(对于函数和数组,它确实如此)。

所以你最终会比较两个字符串。在函数对象上调用 toString 的结果不是由规范定义,尽管大多数主要引擎返回函数的源代码(或其某种形式,并且格式各不相同)。在数组上调用 toString 的结果是相同的作为加入

因此,您最终基本上会这样做的可能性是:

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

由于该函数的字符串的确切形式可能因浏览器而异(并注意 Esailija 的调查 ——看起来 IE9 保留了外部 (),Chrome 没有),结果可能并不令人意外 各不相同。

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).

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 calling toString on arrays is the same as 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.

亣腦蒛氧 2025-01-15 06:34:51

让我们深入了解 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 函数。虽然如果可以的话,这偏向于返回数字,但也可以派生字符串。一旦发生这种情况,将检查以下内容:

a.如果 py 是 px 的前缀,则返回 false。 (字符串值 p 是字符串值 q 的前缀,如果 q 可以是
连接 p 和其他一些字符串 r 的结果。请注意,任何
字符串是其自身的前缀,因为 r 可能是空字符串。)

b.如果 px 是 py 的前缀,则返回 true。

c.令 k 为最小的非负整数使得 px 内位置 k 处的字符不同于 py 内位置 k 处的字符。 (一定有这样的 ak,因为两个字符串都不是另一个字符串的前缀。)

d.令 m 为整数,即 px 内位置 k 处的字符的代码单元值。 e.令 n 为整数,即 py 中位置 k 处的字符的代码单元值。 f.如果m< n,返回真。否则,返回 false。

这意味着将检查字符串中与其他字符不同的第一个字符。正如 Esailija 所指出的,IE 的 toString() 函数返回的字符串与其他浏览器的字符串略有不同,从而导致发生不同的比较。

浏览器之间的这种差异似乎是有效的,如下所述:

15.2.4.4 Object.prototype.valueOf ( )

当调用 valueOf 方法时,会执行以下步骤:

  1. 令 O 为调用 ToObject 并传递 this 值作为参数的结果。
  2. 如果 O 是使用宿主对象 (15.2.2.1) 调用对象构造函数的结果,则 a。返回 O 或其他值,例如
    最初传递给构造函数的宿主对象。具体的
    返回的结果是实现定义的。
  3. 返回O。

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 production RelationalExpression : RelationalExpression >
ShiftExpression is evaluated as follows:

  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be GetValue(rref) .
  5. Let r be the result of performing abstract relational comparison rval < lval with LeftFirst equal to false. (see
    11.8.5).

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:

a. If py is a prefix of px, return 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.)

b. If px is a prefix of py, return true.

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. (There must be such a k, for neither String is a prefix of the other.)

d. Let m be the integer that is the code unit value for the character at position k within px. e. Let n be the integer that is the code unit value for the character at position k within py. f. If m < n, return true. Otherwise, return false.

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 ( )

When the valueOf method is called, the following steps are taken:

  1. Let O be the result of calling ToObject passing the this value as the argument.
  2. If O is the result of calling the Object constructor with a host object (15.2.2.1), then a. Return either O or another value such as
    the host object originally passed to the constructor. The specific
    result that is returned is implementation-defined.
  3. Return O.
美胚控场 2025-01-15 06:34:51

IE 和其他浏览器都会对这两个对象使用相同的字符串比较。差异的原因是 IE 会将函数转换为输入的文字字符串:

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

其他浏览器(在 Firefox 上测试)将输出其自己编译的函数解释:

function (x) {
    return x * x;
}

由于 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:

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

Other browsers (testing on Firefox) will output its own compiled interpretation of the function:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文