为什么for不能有序遍历数组的所有元素?(Array的设计原理)
这个题目略微浅显,但却不易讲明白。如果我告诉你,我们不能以任何代码保证可以有序遍历出一个数组的所有元素,你肯定会反驳我,因为使用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的设计原理)的更多相关文章
- 遍历数组中的元素(含es6方法)
假如有这样一个数组.arr = [12,34,45,46,36,58,36,59],现在要遍历该数组. 方法1:以前我们可能会这样做: for(var i=0;i<arr.length;i++) ...
- 用C#中的键值对遍历数组或字符串元素的次数
代码如下: string strs = "ad6la4ss42d6s3"; Dictionary<char, int> dic = new Dictionary< ...
- Struts2的OGNL遍历数组、List、简单的Map
一.简介 <s:iterator />可以遍历 数据栈里面的任何数组,集合等等 在使用这个标签的时候有三个属性值得我们关注 1. value属性:可选的属性,value属性是指一 ...
- IT兄弟连 Java语法教程 数组 使用foreach循环遍历数组元素
从JDK5之后,Java提供了一种更简单的循环:foreach循环,也叫作增强for循环,这种循环遍历数组和集合更加简洁.使用foreach循环遍历数组和集合元素时,无需获得数组或集合的长度,无需根据 ...
- PHP数组——定义,类型,遍历数组,数组函数
1.定义 $attr=array(); //标准定义方式 $attr=[1,2]; $attr[0]="hello"; ...
- 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中
转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比 ...
- [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 ...
- [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 ...
- LeetCode 88. 合并两个有序数组(Merge Sorted Array)
题目描述 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m ...
随机推荐
- Java和.NET在开发中的不同盘点
我是用VS2008和VS2010开发.NET程序,通过MyEclipse8.5开发JAVA程序,下面从IDE.语言.插件的不同点来做下简单的说明.但由于经验知识还有限,本篇文章只能从比较表面的以及自己 ...
- Reduce对Pig作业性能的影响
Amber Zhao Wed, Feb 25 2015 3:36 AM 很多用户在使用HDInsight的Pig功能时,发现有时很简单一个Pig Latin的relation会花费很长时间执行,当H ...
- 【转】UIColor对颜色的自定义
原文网址:http://blog.sina.com.cn/s/blog_5f19ccb10101bhqh.html 在iOS开发中,我们使用UIColor来对我们的界面进行颜色设置,一般我们通过以下两 ...
- 使用 document.onreadystatechange()来判断页面加载完
document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法. function subSomething() { if(docum ...
- JS组件Bootstrap实现弹出框和提示框效果代码
这篇文章主要介绍了JS组件Bootstrap实现弹出框和提示框效果代码,对弹出框和提示框感兴趣的小伙伴们可以参考一下 前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编 ...
- jdbc三种常见用法
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...
- docker专题(2):docker常用管理命令(上)
http://segmentfault.com/a/1190000000751601 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备 ...
- Apache-AB压力测试实例
一 AB背景介绍 Apache附带的压力测试工具apache bench--简称ab,非常容易使用,并且完全可以摸你各种条件对Web服务器发起测试请求.ab可以直接在Web服务器本地发起测试请求,这对 ...
- ajax post方法
定义和用法 post() 方法通过 HTTP POST 请求从服务器载入数据. 语法 jQuery.post(url,data,success(data, textStatus, jqXHR),dat ...
- iBatis之type
iBatis下关于type的UML图,展示iBatis下关于类型的处理和注册等.