indexOf 与比较操作

 

  现在我已经大量在平时应用中应用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

Checks whether or not the specified object exists in the array.
Checks whether or not the specified object exists in the array.
Parameters:
  • o : Object
    The object to check for
Returns:
  • Number
    The index of o in the array (or -1 if it is not found)

先不管 是否他是 完全相等 (===) 或 相容相等(==) ,至少我们期望在各个浏览器上表现一致,但是很不幸,据我测试

ie 系列 : alert 0
firefox 系列 : alert -1


那么查看 Extjs 的源代码:( 注意:  代码存在 ext-2.2.1/adapter/ext-base.js   与 source/core/Ext.js  并不存在于 source/adapter/ext-base.js

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值