这个题目略微浅显,但却不易讲明白。如果我告诉你,我们不能以任何代码保证可以有序遍历出一个数组的所有元素,你肯定会反驳我,因为使用for明明就可以啊!但其实不是。

一、为什么FOR不能保证遍历所有?

代码0:

var arr1 :Array = ["as3", "expert", "programming"];arr1.name = "sban";for(var j:int=0; j{trace(arr1[j]);}

代码0仅能遍历出3个元素,原因在于动态添加的元素name是在Object上添加的,因Array是动态对象所以可以这样行码,但它并不受Array管理,也并未被统计在length之中。

二、ARRAY对象是如何设计的?

Array继承于Object,是动态对象,使用动态属性直接在Object上存储数据。当下标与元素的对应关系发生变化时,受到影响的属性名称会全部重写。Array在内部维护一个length属性,元素的改变不受制于length,length因元素而改变。(注:此观点乃sban个人推测,非官方,接爱请审慎)

据上一段,我们可以推断:

1,设有数组arr1,arr1[0]元素的属性名称为“0”,使用arr1[0]访问数组元素与使用arr1[“0”]的效果是相同的

2,对于大数组的添加元素操作,push的效率远远高于unshift

3,数组既可以使用for遍历,也可以使用for in与for each in遍历,后两者是所有Object都具有的遍历方法。

4,可以无视数组的定义长度,跳跃指定元素的下标。

让我们验证一下我们的推断:

代码1:

var arr1 :Array = ["as3", "expert", "programming"];trace(arr1[0], arr1["0"]);//as3 as3

代码2:

var arr1 :Array = [], arr2 :Array = [];

var t1:Number, t2:Number;t1 = new Date().getTime();for(var j:Number=0;j<100000;j++){arr1.push(j);}t2 = new Date().getTime();trace("push耗约:", t2-t1);//push耗约: 35t1 = new Date().getTime();for(var j:Number=0;j<100000;j++)//这个数值如果太大,比如5千万,你会发现你的电脑根本就无法完成它{arr2.unshift(j);}t2 = new Date().getTime();trace("unshift循环耗约:", t2-t1);//unshift循环耗约: 7881

代码3://遍历一个5千万的数组,用三种方法遍历及速度对比

var t1:Number, t2:Number;var arr1 :Array = [];for(var j:Number=0;j<50000000;j++)//for遍历{arr1.push(j);}t1 = new Date().getTime();for each(var p:* in arr1)//for each in遍历{var i1:* = p;}t2 = new Date().getTime();trace("for each in耗约:", t2-t1);//for each in耗约: 8891t1 = new Date().getTime();for(var p:* in arr1)//for遍历{var i2:* = arr1[p];}t2 = new Date().getTime();trace("for in耗约:", t2-t1);//for in耗约: 9861t1 = new Date().getTime();var n:Number = arr1.length;for(var k:Number=0; k<n; k++){var i3:* = arr1[k];}t2 = new Date().getTime();trace("for耗约:", t2-t1);//for耗约: 9720

代码4://无视数组既有长度,跳跃指定元素的下标

var arr :Array = new Array(1);arr['2'] = "sban";//arr[2] = "sban",使用数字与字符串作下标,效率是相同的,AS3内部会作必要的类型转化trace("length:", arr.length);for(var j:int=0; j<arr.length; j++){trace(arr[j]);}/* length: 3 undefined undefined sban */

这个白痴的特性让人很失望!C语言的数组从来都是先分配大小的,不充许越界赋值。AS3的Array的length变得没有任何实际意义,它既不能限制数组元素的随意添加,也不能正确的彰显数组到底有多少元素。

三、为什么ADOBE要把ARRAY设计为动态对象?

在AS3中,其它基本数据类型如String,Number均是非动态对象,为什么Array要被设计为动态对象?Adobe为什么要充许外部代码在Array上动态创建属性?Array作为数组,竟然可以拥有自己的动态属性,貌似这是一个很不合理的设计。

作者并非在Adobe工作,并不了解如此设计的真正玄机。sban看过一份Flash Player v4 v++源码,但Array是Flash Player 9之后才出现的,里面并没有关于Array的相关代码。

sban推测正则表达式的命名组功能是促使Adobe把Array设计为动态对象的主要原因之一。

代码4:

var s :String = “as expert programming by sban.“;var arr : Array = /by (?P\w+)/i.exec(s);trace(arr.name);//sbantrace(arr is Array);//true

对于正则的exec方法,如何保证在返回数组对象的同时,该对象又具有用户指定的动态属性,把Array设计为动态对象是最简洁的方法之一,并且这与AS3是一门纯面向对象语言的思想并不违悖。

四、总结

遍历一个数组有三种方法:

1,for遍历

2,for in遍历

3,for each in遍历

如果要保证有序遍历,只能使用方法一,但不能保证遍历所有;如果要保证遍历所有,可以使用方法2或3,但不能保证有序。三种方法遍历小数组的效率没有差别,遍历大数组时略有差别。

五、建议

存储无序元素集合,使用Object优于Array。

Optimus 2008/4/1 北京

本文采用署名-非商业性使用-相同方式共享协议,属于AS3-Expert的一部分,转载请注明作者 及出处,非商业。

如果您是Flash/AS3技术的爱好者,请加入AS3高级技术群:44985308,70782097。如果你是Flash/AS3方面的专家,请加入AS3专家群(71057902),申请验证请附上作品链接或博客地址。

为什么for不能有序遍历数组的所有元素?(Array的设计原理)的更多相关文章

  1. 遍历数组中的元素(含es6方法)

    假如有这样一个数组.arr = [12,34,45,46,36,58,36,59],现在要遍历该数组. 方法1:以前我们可能会这样做: for(var i=0;i<arr.length;i++) ...

  2. 用C#中的键值对遍历数组或字符串元素的次数

    代码如下: string strs = "ad6la4ss42d6s3"; Dictionary<char, int> dic = new Dictionary< ...

  3. Struts2的OGNL遍历数组、List、简单的Map

    一.简介 <s:iterator />可以遍历 数据栈里面的任何数组,集合等等 在使用这个标签的时候有三个属性值得我们关注      1. value属性:可选的属性,value属性是指一 ...

  4. IT兄弟连 Java语法教程 数组 使用foreach循环遍历数组元素

    从JDK5之后,Java提供了一种更简单的循环:foreach循环,也叫作增强for循环,这种循环遍历数组和集合更加简洁.使用foreach循环遍历数组和集合元素时,无需获得数组或集合的长度,无需根据 ...

  5. PHP数组——定义,类型,遍历数组,数组函数

    1.定义 $attr=array();                            //标准定义方式 $attr=[1,2]; $attr[0]="hello";     ...

  6. 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中

    转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比 ...

  7. [leetcode]26. Remove Duplicates from Sorted Array有序数组去重(单个元素只出现一次)

    Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...

  8. [LeetCode] 34. Find First and Last Position of Element in Sorted Array 在有序数组中查找元素的第一个和最后一个位置

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  9. LeetCode 88. 合并两个有序数组(Merge Sorted Array)

    题目描述 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m ...

随机推荐

  1. 自定义一个compass可编译的目录结构

    在学习compass的过程中, 根绝文档说明,如果使用compass create myObject命令会创建一个标准的Compass项目目录结构,如下图: 此时如果使用compass compile ...

  2. 为自己打造Linux小系统

     一.前言 Linux操作系统至1991.10.5号诞生以来,就源其开源性和自由性得到了很多技术大牛的青睐,每个Linux爱好者都为其贡献了自己的一份力,不管是在Linux内核还是开源软件等方面,都为 ...

  3. RMAN 备份与恢复深入解析(二)

    RMAN 备份与恢复深入解析(一)  http://space.itpub.net/26686207/viewspace-760869 更多精彩内容尽在 www.leonarding.com < ...

  4. 使用BusyBox制作Linux根文件系统

    STEP 1:构建目录结构 创建根文件系统目录,主要包括以下目录/dev  /etc /lib  /usr  /var /proc /tmp /home /root /mnt /bin  /sbin  ...

  5. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.4.1

    Let $x,y,z$ be linearly independent vectors in $\scrH$. Find a necessary and sufficient condition th ...

  6. “菜单”(menubar)和“工具栏”(toolbars)

    "菜单"(menubar)和"工具栏"(toolbars) "菜单" (menubar)和"工具栏"(toolbars) ...

  7. 用JSP做后台管理系统

    添加新闻 /**  * 获取从页面读取的数据  * @param request  * @return 单个新闻信息  * @throws UnsupportedEncodingException   ...

  8. 浅析ado.net获取数据库元数据信息 DeriveParameters

    写这个文章源于早先对ADO.Net获取数据库元数据上的认识,去年我在阅读ADO.Net Core Reference的时候曾经注意过DataSet的FillSchema的这个方法.这方面,在我之前的随 ...

  9. 数据库设置表的check约束出现乱码

    采用默认的方式见了一个数据库,但是有个表里需要建一个check约束.将约束保存之后再打开看到中文成了??.后来查了一下是数据库排序规则除了问题. 详见两图即可明白: 这里的约束中文显示乱码: 按下图设 ...

  10. Code First 更新数据库结构

    参考:http://blog.csdn.net/sxycxwb/article/details/12186159 0.删除之前的数据库 1.Run the Enable-Migrations comm ...