javascript中length属性的探索


Posted in Javascript onJuly 31, 2011

例子1:

var obj={0:'a',1:'b'} 
alert(obj.length); //undefined 
var arr=['a','b'] 
alert(arr.length); // 2

从上面的例子看,类数组对象中的length属性并不和它储存的数据数量直接挂钩,无论是索引属性(0,1)还是length属性都作为对象的普通属性存在,它们之间并没有任何关系,js引擎并不会根据储存数据的数量来自动计算类数组对象的长度。
但是类数组对象的length所确实和存储的数据量没有任何关系么?例子2说明并非如此:
例子2:
function myarr(){} 
var m=new myarr(); 
Array.prototype.push.apply(m,['cson','lai','xiaoc']); 
alert(m.length);//IE8以下:undefined 其他浏览器:3 
alert(m[2]);//IE8以下:undefined 其他浏览器:‘xiaoc'

从例子2可以看到,除了IE8以下版本,在通过强制使用数组方法为类数组对象添加元素时,对象的length属性也会被计算。而IE8以下版本貌似不支持强制使用数组方法为类数组对象添加元素。
例子3:
该例子在例子2的myarr构造函数中添加一个初始化操作,在类数组对象初始化时添加一个元素,怪异的事情发生了:
function myarr(){this[0]='cc';} 
var m=new myarr(); 
Array.prototype.push.apply(m,['cson','lai','xiaoc']); 
alert(m.length);//ie8以下:undefined 其他:3 
alert(m[2]);//ie8以下:undefined 其他:xiaoc

ie8以下版本浏览器继续貌似不支持强制使用数组方法,这个再下一个例子中会作讨论。而对于其他浏览器,length属性输出为3,而索引为2的元素是'xiaoc‘,显然js引擎完全忽略了类数组对象原来所存在的索引为0的元素‘cc'!马上我们再看下一个例子,这个例子在例子3的基础上多加一个对length属性的初始化:
function myarr(){this[0]='cc'; this.length=1;}//多加一个length的初始化 
var m=new myarr(); 
Array.prototype.push.apply(m,['cson','lai','xiaoc']); 
alert(m.length);//输出4 
alert(m[2]);//输出'lai‘

奇怪的事再次发生,这次所有浏览器(包括ie6 7)都正确输出4,索引为2的元素正确输出为'lai‘,可见IE 6 7添加了length属性的初始化之后,可以正常使用数组方法了。
现在再试试把length属性初始化为不合法类型:
例子4:
function myarr(){this[0]='cc'; this.length="bo";}//length设置为不能转换为number的不合法类型 
var m=new myarr(); 
Array.prototype.push.apply(m,['cson','lai','xiaoc']); 
alert(m.length);//输出 3 
alert(m[2]);// 输出'xiaoc‘

function myarr(){this[0]='cc'; this.length="1";}//length设置为能转换为数字的不合法类型 
Array.prototype.push.apply(m,['cson','lai','xiaoc']); 
alert(m.length);//输出4 
alert(m[2]);//输出'lai‘

从上面的所有例子来看,我们可以作出一个推断,在使用数组方法时(这里以push为例),大概是这样的流程:
IE6 7:
可见IE6 7并非不支强制持使用数组方法添加元素,但是会先判断length属性是否存在,如果不存在,则返回,不做任何操作。如果length属性为不合法值,则尝试转换为number类型,如果转换失败则length设置为0,这就可以解析例子2,3里输出的undefined和例子4的正确输出。

其他浏览器:
其他浏览器会根据length属性作不同操作,如果length属性不存在,则设置length为0,如果length属性为不合法值,则尝试转换为number类型,如果转换失败则也length设置为0。

正因为length属性对于数组方法有如此决定性的作用,因此js引擎禁止了对length属性写入不合法值:

var arr=['1','2','3']; 
arr.length='undefined';//报错invalid array length

从上面的例子中,我们可以得出一个结论:当我们使用类数组对象时,为了避各种length计算不正确引起的怪异问题,我们应该在初始化类数组对象时初始化length属性的值,如果在初始化时添加了元素但却没有设置length属性的值,在使用数组方法时,IE6 7会忽略所有操作,其他浏览器则会忽略初始化时添加的元素。

另外再介绍length属性带来的另一个问题:
请看例子5:

function myarr(){} 
myarr.prototype=new Array(); 
var m=new myarr(); 
m.push('cson','lai','xiaoc'); 
alert(m.length);//IE6 7:0 其他:3 
alert(m[2]);//所有浏览器:'xiaoc‘

当使用原型继承数组时,IE 6 7下length会始终为0,无论你有多少个元素,其他浏览器则正常。
即使强制设置length属性,IE6 7 下死活为0:
function myarr(){} 
myarr.prototype=new Array(); 
var m=new myarr(); 
m.length=10; 
alert(m.length);//IE6 7:0 其他:10

因此得出结论:IE6 7下对象原型继承数组时length属性会一直为0,因此如果类数组对象需要使用数组的方法,不要去继承数组,而应该使用Array.prototype.xxx.apply(obj,[]);的方法,并且记得正确初始化length属性的值。
Javascript 相关文章推荐
this[] 指的是什么内容 讨论
Mar 24 Javascript
javascript引用对象的方法代码
Aug 13 Javascript
表单元素事件 (Form Element Events)
Jul 17 Javascript
jQuery中each()方法用法实例
Dec 27 Javascript
javascript使用正则表达式实现去掉空格之后的字符
Feb 15 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
Oct 10 Javascript
10分钟掌握XML、JSON及其解析
Dec 06 Javascript
JS实现按钮控制计时开始和停止功能
Jul 27 Javascript
JS打印彩色菱形的实例代码
Aug 15 Javascript
基于vue如何发布一个npm包的方法步骤
May 15 Javascript
利用Vue-draggable组件实现Vue项目中表格内容的拖拽排序
Jun 07 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
Feb 13 Javascript
javascript string字符串优化问题
Jul 31 #Javascript
超级有用的13个基于jQuery的内容滚动插件和教程
Jul 31 #Javascript
基于JQuery 的消息提示框效果代码
Jul 31 #Javascript
使用基于jquery的gamequery插件做JS乒乓球游戏
Jul 31 #Javascript
JQuery通过Ajax提交表单并返回结果
Jul 31 #Javascript
Dreamweaver jQuery智能提示插件,支持版本提示,支持1.6api
Jul 31 #Javascript
动态加载外部javascript文件的函数代码分享
Jul 28 #Javascript
You might like
全国FM电台频率大全 - 17 湖北省
2020/03/11 无线电
php线性表顺序存储实现代码(增删查改)
2012/02/16 PHP
ThinkPHP模板之变量输出、自定义函数与判断语句用法
2014/11/01 PHP
PHP封装CURL扩展类实例
2015/07/28 PHP
深入讲解PHP Session及如何保持其不过期的方法
2015/08/18 PHP
浅谈laravel框架sql中groupBy之后排序的问题
2019/10/17 PHP
PHP7移除的扩展和SAPI
2021/03/09 PHP
用js实现的一个Flash滚动轮换显示图片代码生成器
2007/03/14 Javascript
js控制的回到页面顶端goTop的代码实现
2013/03/20 Javascript
基于JavaScript代码实现兼容各浏览器的设为首页和加入收藏
2016/01/07 Javascript
BootStrap与validator 使用笔记(JAVA SpringMVC实现)
2016/09/21 Javascript
AngularJS实现用户登录状态判断的方法(Model添加拦截过滤器,路由增加限制)
2016/12/12 Javascript
浅谈vue,angular,react数据双向绑定原理分析
2017/11/28 Javascript
ionic grid(栅格)九宫格制作详解
2018/06/30 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
Vue路由管理器Vue-router的使用方法详解
2020/02/05 Javascript
JS数组Reduce方法功能与用法实例详解
2020/04/29 Javascript
Vue中computed及watch区别实例解析
2020/08/01 Javascript
Vue 样式切换及三元判断样式关联操作
2020/08/09 Javascript
python判断windows隐藏文件的方法
2014/03/21 Python
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
举例区分Python中的浅复制与深复制
2015/07/02 Python
Python 多核并行计算的示例代码
2017/11/07 Python
python3实现windows下同名进程监控
2018/06/21 Python
python for循环输入一个矩阵的实例
2018/11/14 Python
浅析rem和em和px vh vw和% 移动端长度单位
2016/04/28 HTML / CSS
HTML5实时语音通话聊天MP3压缩传输3KB每秒
2019/08/28 HTML / CSS
鱼油专家:Omegavia
2016/10/10 全球购物
几道Web/Ajax的面试题
2016/11/05 面试题
师范生实习个人的自我评价
2013/09/28 职场文书
村官学习十八大感想
2014/01/15 职场文书
教师个人鉴定材料
2014/02/08 职场文书
力学专业求职信
2014/07/23 职场文书
国庆节活动总结
2014/08/26 职场文书
处级干部考察材料
2014/12/24 职场文书
婚宴来宾致辞
2015/07/28 职场文书