这个题目略微浅显,但却不易讲明白。如果我告诉你,我们不能以任何代码保证可以有序遍历出一个数组的所有元素,你肯定会反驳我,因为使用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. 在“BindingNavigator”删除数据前弹出确认框的实现

    1)先设置DeleteItem为空,不让它调用自动生成的删除代码. 2)然后自己写代码实现,如下: private void bindingNavigatorDeleteItem_Click(obje ...

  2. C# 实例化顺序

    static class Program { static void Main() { BaseB baseb = new BaseB(); baseb.MyFun(); Console.ReadKe ...

  3. jquery M97-datepicker日历控件

    My97DatePicker是一款非常灵活好用的日期控件.使用非常简单. 1.下载My97DatePicker组件包 2.在页面中引入该组件js文件:     <script type=&quo ...

  4. android xml文件

    一.布局文件:在layout目录下,使用比较广泛: 我们可以为应用定义两套或多套布局,例如:可以新建目录layout_land(代表手机横屏布局),layout_port(代表手机竖屏布局),系统会根 ...

  5. HDU 3271-SNIBB(数位dp)

    题意:给一个数q, q=1时求给定区间,给定进制,各数位和等于m的数字的个数 q=2时求给定区间,给定进制,各数位和等于m的数字中的第k大的数字 分析:dp[i][sum][j],表示长度为i当前数位 ...

  6. QTP检查点和参数化_百度一下

    一.脚本编辑检查点: Browser("百度知道 - 全球最大中文互动问答平台").Page("百度知道 - 全球最大中文互动问答平台").WebEdit(&q ...

  7. Robotium自动化测试报告生成

    使用Robotium进行测试的时候,要想可以导出可视的测试结果,可以使用junitreport来实现junitreport下载地址:https://github.com/jsankey/android ...

  8. js 数组常用方法说明

    //push 向数组最后添加一项 var arr = ['one', 'two', 'three']; arr.push("four"); console.log(arr);//[ ...

  9. Integrating JavaScript into Native Applications

    JavaScriptCore 简介 iOS7 中新加入的 JavaScriptCore.framework 可能被大多数开发人员所忽略,但是如果你之前就在项目中用过自己编译JavaScriptCore ...

  10. [GRYZ2015]快排练习

    用快排完成n(n<=100)个人年龄的从小到大的排序,要求出生年相同的按月排. 输入:第一行n个人 2到n+1行出生  年  月(1992 9) 输出:年龄的从小到大的排序. type ss=r ...