javascript中length属性的探索

 更新时间:2011年07月31日 21:32:39   作者:  
本文中,我将会通过类数组对象(array like object),探索javascript中的length属性的一些秘密。
例子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属性的值。

相关文章

  • js中substring和substr的定义和用法

    js中substring和substr的定义和用法

    这篇文章主要介绍了js中substring和substr的定义和用法,需要的朋友可以参考下
    2014-05-05
  • MySQL SUM Function函数使用详解

    MySQL SUM Function函数使用详解

    这篇文章主要为大家介绍了MySQL SUM Function函数使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • JavaScript中call和apply方法的区别实例分析

    JavaScript中call和apply方法的区别实例分析

    这篇文章主要介绍了JavaScript中call和apply方法的区别,结合实例形式分析call和apply方法的功能、原理及相关使用操作区别,需要的朋友可以参考下
    2018-08-08
  • JS复制对应id的内容到粘贴板(Ctrl+C效果)

    JS复制对应id的内容到粘贴板(Ctrl+C效果)

    这篇文章主要给大家介绍了利用JS实现复制指定对应id的内容到粘贴板(Ctrl+C效果),文中给出了详细的介绍和示例代码,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • JS提交form表单实例分析

    JS提交form表单实例分析

    这篇文章主要介绍了JS提交form表单的方法,结合实例形式简单分析了页面加载时提交表单及通过链接提交表单的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-12-12
  • js 判断控件获得焦点的示例代码

    js 判断控件获得焦点的示例代码

    本篇文章主要是对js 判断控件获得焦点的示例代码进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-03-03
  • 浅谈js中字符和数组一些基本算法题

    浅谈js中字符和数组一些基本算法题

    下面小编就为大家带来一篇浅谈js中字符和数组一些基本算法题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • js实现网页音乐播放器

    js实现网页音乐播放器

    这篇文章主要为大家详细介绍了js实现网页音乐播放器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Javascript中的call()方法介绍

    Javascript中的call()方法介绍

    这篇文章主要介绍了Javascript中的call()方法介绍,本文讲解了Call() 语法、Call() 参数、Javascript中的call()方法、Call()方法的实例等内容,需要的朋友可以参考下
    2015-03-03
  • bootstrap treeview 树形菜单带复选框及级联选择功能

    bootstrap treeview 树形菜单带复选框及级联选择功能

    这篇文章主要介绍了bootstrap treeview 树形菜单带复选框及级联选择功能,代码超简单,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-06-06

最新评论