为JS扩展Array.prototype.indexOf引发的问题探讨及解决


Posted in Javascript onApril 24, 2013

Array没有indexOf方法,这样在一个数组中查找某个元素的索引时比较麻烦,为了调用方便,于是通过prototype原型扩展了Array.prototype.indexOf(),这样用起来就比较方便了。但是这个自定义的indexOf在对数组进行遍历的时候却出现了问题。

Array没有indexOf方法,这样在一个数组中查找某个元素的索引时比较麻烦,为了调用方便,于是通过prototype原型扩展了Array.prototype.indexOf(),这样用起来就比较方便了。

Array.prototype.indexOf = function(item) { 
for (var i = 0; i < this.length; i++) { 
if (this[i] == item) 
return i; 
} 
return -1; 
}

用的时候直接
var arr=[1,2,3,4,5]; 
var index=arr.indexOf(1); //index==0

扩展了以后,用起来很爽很方便,一片和谐景象...
但是某次是遍历数组元素的时候,使用for..in..循环,引发了其他的问题,打破了这个和谐的氛围。
var a=["张飞","关羽","刘备","吕布"]; 
for(var p in a){ 
document.write(p+"="+a[p]+"<br/>"); 
}

本来想输出这四个人的名字,结果输出的是什么呢?
输出的居然是:
//0=张飞
//1=关羽
//2=刘备
//3=吕布
//indexOf=function(item) { for (var i = 0; i < this.length; i++) { if (this[i] == item) return i; } return -1; }
除了把名字打出来以外,还额外输出了自己扩展的方法indexOf,但是令人疯狂的是,firefox却是“正常”的,只有四个人的人名,为什么会这样?
输出indexOf,自己扩展的,可以理解,毕竟for..in是遍历一个对象的所有用户定义的属性或者一个数组的所有元素。
那么firefox为什么不会?
后来查了资料才明白,
Array在javascript1.6版本已经支持Array.indexOf(),而我用的firefox是3.5版本,已经支持javascript1.8了,indexOf是其Array本身固有的方法了。
而IE,即使我用的是IE8,也才支持到javascript1.3版本。
所以IE8认为indexOf是“用户定义的属性”,而firefox认为是自己原生支持的固有的属性。
真的是这样吗?
做个实验,把indexOf更名为myIndexOf,再试试,结果IE和firefox都输出myIndexOf,证明前面的观点是正确。
那么又来了个问题,我扩展indexOf很久了,现在不少项目的代码都已经在使用这个方法,而现在我非要使用for..in输出数组本身的元素,不要其他我自己扩展到俄方法,怎么办?
好在javascript提供了hasOwnProperty方法。
看一下其描述:
Every object descended from Object inherits the hasOwnProperty method. This method can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain
看描述,就是我们想要的东西。
在for...in..里做个 判断就OK了
if(a.hasOwnProperty(p)){ 
document.write(p+"="+a[p]+"<br/>"); 
}

另外,附上hasOwnProperty用法示例,来源于互联网:
function Book(title, author) { 
this.title = title; 
this.author = author; 
} 
Book.prototype.price = 9.99; 
Object.prototype.copyright = "herongyang.com"; 
var myBook = new Book("JavaScript Tutorials", "Herong Yang"); 
// Dumping built-in properties at the base prototype level 
document.writeln("/nObject.prototype's built-in properties:"); 
dumpProperty(Object.prototype, "constructor"); 
dumpProperty(Object.prototype, "hasOwnProperty"); 
dumpProperty(Object.prototype, "isPrototypeOf"); 
dumpProperty(Object.prototype, "toString"); 
dumpProperty(Object.prototype, "valueOf"); 
dumpProperty(Object.prototype, "copyright"); 
// Dumping built-in properties at the my prototype level 
document.writeln("/n==================/nBook.prototype's built-in properties:"); 
dumpProperty(Book.prototype, "constructor"); 
dumpProperty(Book.prototype, "hasOwnProperty"); 
dumpProperty(Book.prototype, "isPrototypeOf"); 
dumpProperty(Book.prototype, "toString"); 
dumpProperty(Book.prototype, "valueOf"); 
dumpProperty(Book.prototype, "copyright"); 
// Dumping built-in properties at the object level 
document.writeln("/n==================/nmyBook's built-in properties:"); 
dumpProperty(myBook, "constructor"); 
dumpProperty(myBook, "hasOwnProperty"); 
dumpProperty(myBook, "isPrototypeOf"); 
dumpProperty(myBook, "toString"); 
dumpProperty(myBook, "valueOf"); 
dumpProperty(myBook, "copyright"); 
function dumpProperty(object, property) { 
var inheritance; 
if (object.hasOwnProperty(property)) 
inheritance = "Local"; 
else 
inheritance = "Inherited"; 
document.writeln(property+": "+inheritance+": " 
+object[property]); 
}

查看浏览器支持javascript到哪个版本:
<!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"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>浏览器的JavaScript版本支持测试</title> 
</head> 
<body> 
<script language="JavaScript"> 
//document.write("您的浏览器类型:"+navigator.appName+"<br/>"); 
//document.write("浏览器版本:"+navigator.appVersion+"<br/>"); 
//支持JavaScript1.0的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.0<br/>'); 
</script> 
<script language="JavaScript1.1"> 
//支持JavaScript1.1的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.1<br/>'); 
</script> 
<script language="JavaScript1.2"> 
//支持JavaScript1.2的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.2<br/>'); 
</script> 
<script language="JavaScript1.3"> 
//支持JavaScript1.3的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.3<br/>'); 
</script> 
<script language="JavaScript1.4"> 
//支持JavaScript1.4的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.4<br/>'); 
</script> 
<script language="JavaScript1.5"> 
//支持JavaScript1.5的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.5<br/>'); 
</script> 
<script language="JavaScript1.6"> 
//支持JavaScript1.6的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.6<br/>'); 
</script> 
<script language="JavaScript1.7"> 
//支持JavaScript1.7的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.7<br/>'); 
</script> 
<script language="JavaScript1.8"> 
//支持JavaScript 1.8的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.8<br/>'); 
</script> 
<script language="JavaScript1.9"> 
//支持JavaScript1.9的浏览器才能够执行该脚本 
document.write('该浏览器支持JavaScript1.9<br/>'); 
</script> 
</body> 
</html>
Javascript 相关文章推荐
jquery使用remove()方法删除指定class子元素
Mar 26 Javascript
javascript动态生成树形菜单的方法
Nov 14 Javascript
AngularJS创建自定义指令的方法详解
Nov 03 Javascript
Vue组件实例间的直接访问实现代码
Aug 20 Javascript
node中间层实现文件上传功能
Jun 11 Javascript
浅谈React碰到v-if
Nov 04 Javascript
小程序如何使用分包加载的实现方法
May 22 Javascript
基于Node的Axure文件在线预览的实现代码
Aug 28 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
May 03 Javascript
如何使用vue slot创建一个模态框的实例代码
May 24 Javascript
解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题
Jul 27 Javascript
解决vue刷新页面以后丢失store的数据问题
Aug 11 Javascript
Dom 学习总结以及实例的使用介绍
Apr 24 #Javascript
jQuery 关于伪类选择符的使用说明
Apr 24 #Javascript
关于ExtJS4.1:快捷键支持的问题
Apr 24 #Javascript
Jquery实现三层遍历删除功能代码
Apr 23 #Javascript
jQuery获取浏览器中的分辨率实现代码
Apr 23 #Javascript
使用PHP+JQuery+Ajax分页的实现
Apr 23 #Javascript
jQuery写的日历(包括日历的样式及功能)
Apr 23 #Javascript
You might like
PHP实现清除MySQL死连接的方法
2016/07/23 PHP
php字符串操作常见问题小结
2016/10/11 PHP
Yii2设置默认控制器的两种方法
2017/05/19 PHP
php中pcntl_fork创建子进程的方法实例
2019/03/14 PHP
php加速缓存器opcache,apc,xcache,eAccelerator原理与配置方法实例分析
2020/03/02 PHP
php中加密解密DES类的简单使用方法示例
2020/03/26 PHP
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
推荐20家国外的脚本下载网站
2011/04/28 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
2015/05/01 Javascript
jQuery动态添加
2016/04/07 Javascript
详解Angular中$cacheFactory缓存的使用
2016/08/19 Javascript
微信小程序 Record API详解及实例代码
2016/09/30 Javascript
js禁止浏览器的回退事件
2017/04/20 Javascript
vue2.0 实现页面导航提示引导的方法
2018/03/13 Javascript
简单的三步vuex入门
2018/05/20 Javascript
TypeScript魔法堂之枚举的超实用手册
2020/10/29 Javascript
[56:41]iG vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/17 DOTA
python转换摩斯密码示例
2014/02/16 Python
简单实现python数独游戏
2018/03/30 Python
python清除字符串中间空格的实例讲解
2018/05/11 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
Python函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数用法实例分析
2019/12/26 Python
tensorflow对图像进行拼接的例子
2020/02/05 Python
OpenCV 表盘指针自动读数的示例代码
2020/04/10 Python
浅谈Python3中print函数的换行
2020/08/05 Python
python中requests模拟登录的三种方式(携带cookie/session进行请求网站)
2020/11/17 Python
纯css3显示隐藏一个div特效的具体实现
2014/02/10 HTML / CSS
Blue Nile台湾:钻石珠宝商,订婚首饰、结婚戒指和精品首饰
2017/11/24 全球购物
Saks Fifth Avenue澳洲/亚太地区:萨克斯第五大道精品百货店
2019/06/09 全球购物
大学毕业感言一句话
2014/02/06 职场文书
医院护士见习期自我鉴定
2014/04/10 职场文书
国际商务专业求职信
2014/07/15 职场文书
2014年档案室工作总结
2014/12/01 职场文书
安全员岗位职责范本
2015/04/11 职场文书
用人单位聘用意向书
2015/05/11 职场文书
详解OpenCV曝光融合
2022/04/29 Python