为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 相关文章推荐
JavaScript 自动分号插入(JavaScript synat:auto semicolon insertion)
Nov 04 Javascript
js 屏蔽鼠标右键脚本附破解方法
Dec 03 Javascript
用jquery生成二级菜单的实例代码
Jun 24 Javascript
JS获取URL中的参数数据
Dec 05 Javascript
node.js开机自启动脚本文件
Dec 24 Javascript
很棒的Bootstrap选项卡切换效果
Jul 01 Javascript
javascript监听页面刷新和页面关闭事件方法详解
Jan 09 Javascript
初探js和简单隐藏效果的实例
Nov 23 Javascript
react中使用css的7中方式(最全总结)
Feb 11 Javascript
VUE+node(express)实现前后端分离
Oct 13 Javascript
JS 图片压缩原理与实现方法详解
Apr 29 Javascript
使用js和canvas实现时钟效果
Sep 08 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
ThinkPHP中ajax使用实例教程
2014/08/22 PHP
ThinkPHP连接数据库及主从数据库的设置教程
2014/08/22 PHP
php多次include后导致全局变量global失效的解决方法
2015/02/28 PHP
微信 getAccessToken方法详解及实例
2016/11/23 PHP
PHP基于面向对象实现的留言本功能实例
2018/04/04 PHP
给网站上的广告“加速”显示的方法
2007/04/08 Javascript
Iframe thickbox2.0使用的方法
2009/03/05 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
window.location的重写及判断location是否被重写
2014/09/04 Javascript
全面了解JavaScript的数据类型转换
2016/07/01 Javascript
js 判断各种数据类型的简单方法(推荐)
2016/08/29 Javascript
jQuery无刷新上传之uploadify简单代码
2017/01/17 Javascript
easyui combogrid实现本地模糊搜索过滤多列
2017/05/13 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
vue 引入公共css文件的简单方法(推荐)
2018/01/20 Javascript
原生JS实现DOM加载完成马上执行JS代码的方法
2018/09/07 Javascript
使用Vue实现移动端左滑删除效果附源码
2019/05/16 Javascript
微信小程序select下拉框实现源码
2019/11/08 Javascript
ES6的异步操作之promise用法和async函数的具体使用
2019/12/06 Javascript
JavaScript对象原型链原理解析
2020/01/22 Javascript
js实现烟花特效
2020/03/02 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
2020/06/22 Javascript
python写一个md5解密器示例
2018/02/23 Python
Scrapy-Redis结合POST请求获取数据的方法示例
2019/05/07 Python
Python安装whl文件过程图解
2020/02/18 Python
Python 调用有道翻译接口实现翻译
2020/03/02 Python
python网络编程:socketserver的基本使用方法实例分析
2020/04/09 Python
numba提升python运行速度的实例方法
2021/01/25 Python
TheFork葡萄牙:欧洲领先的在线餐厅预订平台
2019/05/27 全球购物
年会主持词结束语
2014/03/27 职场文书
长城英文导游词
2015/01/30 职场文书
刮痧观后感
2015/06/05 职场文书
房地产置业顾问工作总结
2015/10/23 职场文书
springboot 自定义配置 解决Boolean属性不生效
2022/03/18 Java/Android
MybatisPlus EntityWrapper如何自定义SQL
2022/03/22 Java/Android