JavaScript类数组对象length属性的行为与IE6/7兼容陷阱
本文深入探讨JavaScript中类数组对象的length属性行为,通过多个代码示例揭示其在不同浏览器中的差异。重点分析IE6和IE7在调用数组方法时对length属性的特殊处理机制,指出未正确初始化length导致的兼容性问题,并提供使用Array.prototype.apply的正确实践建议。
类数组对象length属性的基本行为
示例1展示了基础情况:
代码如下:
var obj={0:'a',1:'b'}
alert(obj.length); //undefined
var arr=['a','b']
alert(arr.length); // 2 从上述示例可以看出,类数组对象中的length属性并不直接反映存储数据的数量。无论是索引属性(如0、1)还是length属性,它们都作为对象的普通属性存在,彼此之间没有自动关联。JavaScript引擎不会根据存储数据的数量自动计算类数组对象的长度。
IE6/7中length属性的特殊处理机制
然而,类数组对象的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‘,显然JavaScript引擎完全忽略了类数组对象原来所存在的索引为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、IE7)都正确输出4,索引为2的元素正确输出为'lai‘,可见IE6、IE7添加了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、IE7:
可见IE6、IE7并非不支持强制使用数组方法添加元素,但是会先判断length属性是否存在,如果不存在,则返回,不做任何操作。如果length属性为不合法值,则尝试转换为number类型,如果转换失败则length设置为0,这就可以解析示例2、3里输出的undefined和示例4的正确输出。
其他浏览器:
其他浏览器会根据length属性作不同操作,如果length属性不存在,则设置length为0,如果length属性为不合法值,则尝试转换为number类型,如果转换失败则也length设置为0。
正因为length属性对于数组方法有如此决定性的作用,因此JavaScript引擎禁止了对length属性写入不合法值:
代码如下:
var arr=['1','2','3'];
arr.length='undefined';//报错invalid array length 从上面的示例中,我们可以得出一个结论:当我们使用类数组对象时,为了避免各种length计算不正确引起的怪异问题,我们应该在初始化类数组对象时初始化length属性的值。如果在初始化时添加了元素但却没有设置length属性的值,在使用数组方法时,IE6、IE7会忽略所有操作,其他浏览器则会忽略初始化时添加的元素。
原型继承数组时的length兼容性问题
另外再介绍length属性带来的另一个问题:
请看示例5:
代码如下:
function myarr(){}
myarr.prototype=new Array();
var m=new myarr();
m.push('cson','lai','xiaoc');
alert(m.length);//IE6、IE7:0 其他:3
alert(m[2]);//所有浏览器:'xiaoc‘ 当使用原型继承数组时,IE6、IE7下length会始终为0,无论你有多少个元素,其他浏览器则正常。
即使强制设置length属性,IE6、IE7下始终为0:
代码如下:
function myarr(){}
myarr.prototype=new Array();
var m=new myarr();
m.length=10;
alert(m.length);//IE6、IE7:0 其他:10 因此得出结论:IE6、IE7下对象原型继承数组时length属性会一直为0,因此如果类数组对象需要使用数组的方法,不要去继承数组,而应该使用Array.prototype.xxx.apply(obj,[]);的方法,并且记得正确初始化length属性的值。
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01
为什么JS中typeof []返回object:数组类型检测误区解析
2026-11-04 19:50:47
