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 相关文章推荐
jQuery .attr()和.removeAttr()方法操作元素属性示例
Jul 16 Javascript
setInterval计时器不准的问题解决方法
May 08 Javascript
JQuery中attr属性和jQuery.data()学习笔记【必看】
May 18 Javascript
AngularJS的脏检查深入分析
Apr 22 Javascript
js+html5实现半透明遮罩层弹框效果
Aug 24 Javascript
vuex学习之Actions的用法详解
Aug 29 Javascript
JavaScript定义函数的三种实现方法
Sep 23 Javascript
JS中判断字符串存在和非空的方法
Sep 12 Javascript
手把手教你 CKEDITOR 4 实现Dialog 内嵌 IFrame操作详解
Jun 18 Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
Oct 15 Javascript
vue-socket.io跨域问题有效解决方法
Feb 11 Javascript
js实现计算器功能
Aug 10 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
自己做矿石收音机
2021/03/02 无线电
ThinkPHP上使用多说评论插件的方法
2014/10/31 PHP
cakephp打印sql语句的方法
2015/02/13 PHP
CodeIgniter实现从网站抓取图片并自动下载到文件夹里的方法
2015/06/17 PHP
基于PHPexecl类生成复杂的报表表头示例
2016/10/14 PHP
PHP设计模式之模板方法模式定义与用法详解
2018/04/02 PHP
PHP项目多语言配置平台实现过程解析
2020/05/18 PHP
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
2013/05/07 Javascript
JavaScript操纵窗口的方法小结
2013/06/28 Javascript
js获取元素外链样式的方法
2015/01/27 Javascript
javascript实现数独解法
2015/03/14 Javascript
JavaScript中的条件判断语句使用详解
2015/06/03 Javascript
详解支持Angular 2的表格控件
2017/01/19 Javascript
Vue.js基础指令实例讲解(各种数据绑定、表单渲染大总结)
2017/07/03 Javascript
webpack+vue+express(hot)热启动调试简单配置方法
2018/09/19 Javascript
Element-ui自定义table表头、修改列标题样式、添加tooltip、:render-header使用
2019/04/11 Javascript
Vue Components 数字键盘的实现
2019/09/18 Javascript
JavaScript实现打砖块游戏
2020/02/25 Javascript
JSONP 的原理、理解 与 实例分析
2020/05/16 Javascript
[47:02]2018DOTA2亚洲邀请赛3月29日 小组赛B组 VP VS paiN
2018/03/30 DOTA
python学习手册中的python多态示例代码
2014/01/21 Python
用Python制作检测Linux运行信息的工具的教程
2015/04/01 Python
python实现通过代理服务器访问远程url的方法
2015/04/29 Python
利用pandas读取中文数据集的方法
2018/07/25 Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
2018/12/18 Python
机器学习实战之knn算法pandas
2019/06/22 Python
python 控制台单行刷新,多行刷新实例
2020/02/19 Python
python数据分析工具之 matplotlib详解
2020/04/09 Python
Python 实现一行输入多个数字(用空格隔开)
2020/04/29 Python
Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
2020/07/14 Python
澳大利亚最受欢迎的美发用品目的地:AMR
2019/08/28 全球购物
幼儿园门卫制度
2014/01/29 职场文书
安卓程序员求职信
2014/02/28 职场文书
2016三八妇女节慰问信
2015/11/30 职场文书
学校中层领导培训心得体会
2016/01/11 职场文书