《AS3 Expert》_3:为什么for不能有序遍历数组的所有元素?

2024-01-05 19:18

本文主要是介绍《AS3 Expert》_3:为什么for不能有序遍历数组的所有元素?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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


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

代码0:
  1. var arr1 :Array = ["as3", "expert", "programming"];
  2. arr1.name = "sban";
  3. for(var j:int=0; j
  4. {
  5. trace(arr1[j]);
  6. }
复制代码
代码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:
  1. var arr1 :Array = ["as3", "expert", "programming"];
  2. trace(arr1[0], arr1["0"]);//as3 as3
复制代码
代码2:
  1. var arr1 :Array = [], arr2 :Array = [];

  2. var t1:Number, t2:Number;
  3. t1 = new Date().getTime();
  4. for(var j:Number=0;j<100000;j++)
  5. {
  6. arr1.push(j);
  7. }

  8. t2 = new Date().getTime();
  9. trace("push耗约:", t2-t1);//push耗约: 35
  10. t1 = new Date().getTime();

  11. for(var j:Number=0;j<100000;j++)//这个数值如果太大,比如5千万,你会发现你的电脑根本就无法完成它
  12. {
  13. arr2.unshift(j);
  14. }

  15. t2 = new Date().getTime();
  16. trace("unshift循环耗约:", t2-t1);//unshift循环耗约: 7881
复制代码
代码3
  1. var t1:Number, t2:Number;
  2. var arr1 :Array = [];

  3. for(var j:Number=0;j<50000000;j++)//for遍历
  4. {
  5. arr1.push(j);
  6. }

  7. t1 = new Date().getTime();
  8. for each(var p:* in arr1)//for each in遍历
  9. {
  10. var i1:* = p;
  11. }

  12. t2 = new Date().getTime();
  13. trace("for each in耗约:", t2-t1);//for each in耗约: 8891

  14. t1 = new Date().getTime();
  15. for(var p:* in arr1)//for遍历
  16. {
  17. var i2:* = arr1[p];
  18. }

  19. t2 = new Date().getTime();
  20. trace("for in耗约:", t2-t1);//for in耗约: 9861
  21. t1 = new Date().getTime();
  22. var n:Number = arr1.length;
  23. for(var k:Number=0; k<n; k++)
  24. {
  25. var i3:* = arr1[k];
  26. }

  27. t2 = new Date().getTime();
  28. trace("for耗约:", t2-t1);//for耗约: 9720
复制代码
代码4:
  1. var arr :Array = new Array(1);
  2. arr['2'] = "sban";//arr[2] = "sban",使用数字与字符串作下标,效率是相同的,AS3内部会作必要的类型转化
  3. trace("length:", arr.length);

  4. for(var j:int=0; j<arr.length; j++)
  5. {
  6. trace(arr[j]);
  7. }
  8. /*
  9. length: 3
  10. undefined
  11. undefined
  12. sban
  13. */
复制代码
这个白痴的特性让人很失望!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。

这篇关于《AS3 Expert》_3:为什么for不能有序遍历数组的所有元素?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573892

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.