现在我已经大量在平时应用中应用Extjs core,问题也时常发生,如 Ext.DomHelper 添加 option 问题 ,
今天又遇到了一个Ext使用中很重要但容易忽略问题 ,与大家共享: 如下面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>indexOf 测试</title> <script type="text/javascript" src="ext-base.js"></script> <script type="text/javascript" src="ext-core.js"></script> <script type="text/javascript"> Ext.onReady(function() { /* Array.prototype['indexOf']= function(o){ for (var i = 0, len = this.length; i < len; i++){ if(this[i] == o) return i; } return -1; }; */ var x=[5001, 5003, 5004]; var y='5001'; var z=x.indexOf(y); alert(z); }); </script> </head> <body> </body> </html>
根据 Extjs API 文档 ,
indexOf ( Object o
) : Number
o
: Object
Number
Ext.applyIf(Array.prototype, { indexOf : function(o){ for (var i = 0, len = this.length; i < len; i++){ if(this[i] == o) return i; } return -1; },
可见 Ext 采用的是相容相等,但是又采用了 Ext.applyIf,那么可以分析到 firefox 并没有得到这个方法:
firefox从1.5 就实现了JavaScript 1.6 (非 ecmascript 标准),而 Array 的 indexOf 方法正是从1.6成为原生方法
而 ie (直至最新的ie8) 实现 ecmascript 标准 262 即 javascrip 1.5,Array 并无 indexOf方法,于是由extjs 设置。
http://en.wikipedia.org/wiki/JavaScript
而 javascrip 1.6 中明确规定是对象在数组中出现的索引,即采用的是严格相等,而 ie 执行extjs 设置的相容相等,这也正解释了为什么 ie ff 会在这个问题上表现不一致。
https://developer.mozilla.org/En/Core_javascript_1.5_reference:objects:array:indexof
我认为 Extjs 需对此负一定责任, John Resig 曾说过库是用来屏蔽各个浏览器差异的 ,而 这个问题正是体现了两个浏览器的迥然不同。
John Resig
Advancing JavaScript with Libraries(1)
http://video.yahoo.com/watch/410472/2391234
Advancing JavaScript with Libraries(2)
http://video.yahoo.com/watch/412541/2395771
对于 Extjs 使用的相容相等,觉得也不是很好,对于这方面应该尽量使用严格相等 === ,在 Douglas Crockford 的
The JavaScript Programming Language 讲座中也提到过。
Douglas Crockford
The JavaScript Programming Language(1)
http://video.yahoo.com/watch/111593/1710507
The JavaScript Programming Language(2)
http://video.yahoo.com/watch/111594/1710553
The JavaScript Programming Language(3)
http://video.yahoo.com/watch/111595/1710607
The JavaScript Programming Language(4)
http://video.yahoo.com/watch/111596/1710658
总之很简单的解决:这个改成 === 就可以了,不过不知道为什么这个问题在Ext3.0 beta 中仍然没有改变.
附录 : == 使用注意
参见 ecma262
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
1. If Type(x) is different from Type(y), go to step 14.
2. If Type(x) is Undefined, return true.
3. If Type(x) is Null, return true.
4. If Type(x) is not Number, go to step 11.
5. If x is NaN, return false.
6. If y is NaN, return false.
7. If x is the same number value as y, return true.
8. Ifxis+0andyis−0,returntrue.
9. Ifxis−0andyis+0,returntrue.
10. Return false.
11.If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same
length and same characters in corresponding positions). Otherwise, return false.
12. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
13.Return true if x and y refer to the same object or if they refer to objects joined to each other (see 13.1.2). Otherwise, return false.
14. If x is null and y is undefined, return true.
15. If x is undefined and y is null, return true.
16.If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
17.If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
18. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
19. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
20.If Type(x) is either String or Number and Type(y) is Object,return the result of the comparison x == ToPrimitive(y).
21.If Type(x) is Object and Type(y) is either String or Number,return the result of the comparison ToPrimitive(x) == y.
22. Return false.
ToPrimitive :
1. Call the [[Get]] method of object O with argument "valueOf".
2. If Result(1) is not an object, go to step 5.
3. Call the [[Call]] method of Result(1), with O as the this value and an empty argument list.
4. If Result(3) is a primitive value, return Result(3).
5. Call the [[Get]] method of object O with argument "toString".
6. If Result(5) is not an object, go to step 9.
7. Call the [[Call]] method of Result(5), with O as the this value and an empty argument list.
8. If Result(7) is a primitive value, return Result(7).
9. Throw a TypeError exception.
所以 == 可能会抛出异常的:
var b={ toString :function(){ return {}; }, valueOf : function(){ return {}; } }; try{ alert(b == 'a'); } catch(e){alert(e);}
再试试这个:
"true" == true
ps:ecma262-5rd 的一些备注
1.一些省心的诀窍,免得读代码的其他人不熟悉转换规则
String comparison can be forced by: "" + a == "" + b.
Numeric comparison can be forced by: +a == +b.
Boolean comparison can be forced by: !a == !b.
2.注意 == 不具有传递性:
var a=new String("xx");var b= "xx" ;var c=new String("xx");
a==b ,b==c but a!=c