《ActionScript权威指南》核心知识点汇总

作者:jimohuoshan
来源:蓝色理想

★序言:《ActionScript权威指南》由Colin Moock原著,赵声攀等翻译。虽然是一本讲解FLASH 5的编程书籍,但它却是我目前所看到过的,国内最好的一本AS入门书籍。感谢本书带我真正步入AS的殿堂!我把这本书看了四五遍,对其进行了支解、扩展和重构,我现在的AS知识体系基本上都是来自这本书,现在我把这其中的精髓提炼成十篇左右的文章,以后每天来贴一篇。
★她虽然是讲AS1.0的,但更多涉及的是AS底层的原理性的东西。这些东西永远不会过时,除非AS真的由解释型语言转变成编译型了,或者语法重写了。另外,如果不特别说明,所有的测试平台都是MX 2004,AS 2.0,也就是说虽然是AS1.0的东西,但我的测试环境是2.0的,它们在2.0中也适用。
★这些都是一些很基础的东西,再加上我总结它们的时候,自己也是入门级,所以他们特别适合AS菜鸟,当然如果你并非Colin Moock那样的AS绝顶高手,最好也看一下,最起码起到查漏补缺的作用。假如你发现有些东西竟然是第一次知道,那我只能很遗憾的告诉你,你还未真正步入AS的殿堂,放下一味追新那浮躁的心,好好看看这些东西吧!
★最后想说的是,由于我自己的水平也是很业余的,所以肯定有很多总结的不对的地方,把它们贴出来,也是希望能有高人帮我纠正一下,火山荣幸&&感激!

★1:typeof操作符可以测得变量的数据类型。例:trace(typeof x); //输出undefined
注:typeof得到的是一个串,例:if (typeof x=="undefined"){……};Undefined必须加上引号!→页码:P27
★2:在AS1.0中,无真正的全局变量,但可以用下面的方法模拟:Object.prototype.myGlobalVariable=myVariable; →P63
★3:{x:10,y:20} //花括号以及被逗号分隔开的属性名/值对表示是一个对象。→P77
★4:任何数字与NaN进行四则运算的结果都为NaN。→P79
★5:屏幕文本域输入的内容一定为串,如果想对其执行数学运算,必须用Number()函数进行转化。→P83
★6:数据类型的自动转换中,转换的只是原数据的拷贝,只是一个临时的转换!→P84
★7:当调用toString()方法把数字转化为串的时候,应该这样写:(100).toString(); //用括号防止“.”被当作小数点。→P82
★8:FLASH使用双精度浮点数,支持大约15位精度的有效数字。注意:精度不等于大小。“大约”又是什么意思呢?→P92
★9:NaN是一种合法的数据类型。但如果两个变量的值都是NaN,他们并不相等。→P94
★10:在AS中,串也可以用单引号表示,单双引号可以交叉使用,但必须首尾层次对应。→P96
★11:含有一个空格的串与空串并不相等:即:"" != " " 。→P101
★12:相对于substr()和slice()函数,subString()函数是最佳的选择,效率最高。→P113
★13:当我们最初定义一个变量的时候,它的值会默认为undefined。→P122
★14:引用一个不存在的变量,会返回undefined。→P123
★15:从理论上说,null类型和undefined类型是一样的。但null值不是由解释程序自动赋值的,而需要我们人为赋值。用以表示不含任何数据类型数据的合法空数据容器。注意:null只等于自身和undefined。→P123
★补充1:一个影片剪辑被卸载掉后,它所包括的变量也就无法再被访问。(卸载的方式包括:unLoadMovie(),载入其它影片,空白关键贞。)
★补充2:时间线上的变量必须先声明,才能在其后的贞中访问,但一旦声明后,就能在所有的贞中访问了。
例如:在主时间线上建立三个空白关键贞,并依次在每贞中写代码:trace(a); var a="huoshan"; trace(a);运行的结果将会是:
undefined
huoshan
huoshan
huoshan
……(同上)
★16:AS模除法中,5%4.5=0.5; 余数可以为小数。→P134
★17:operand1 || operand2 从理论上讲,处理逻辑or的第一个步骤是将operand1转换为布尔,如果转换的结果是true,那么逻辑or就返回operand1的值;否则逻辑or就转向operand2进行求值。如果operand1已经可以转换为true,就不再理会operand2。→P146
★18:逻辑and和or的运算机理相似。→P148
★19:delete操作符可删除一个对象,一个对象属性,一个数组元素,或变量。→P153
★20:数组元素操作符可用作对象属性操作符。例:ball["radius"]=150;其实,从功能上说,点操作符和[]操作符在功能上是一样的,可以用来设置和获取对象的属性值。 →P153
★21:条件操作符的语法格式:condition ? result_if_true : result_if_false; 例:
Var guess"c";
Var answer="d";
Var response = (guess==answer) ? "right" : "wrong";
如果guess等于answer,则response的值为"right",如果不是,则response的值为"wrong"; →P154
★22:function function_name(argument_list) {};上面的语句中,function 是函数声明语句,function_name是一个标识符(函数标识符),()是函数调用操作符。→P154
★23:function语句总是必须包含一个语句块,即使被声明的函数中只包含一个语句。→P159
★24:没有return语句的函数将返回undefined。→P164
★25:条件语句的测试表达式不一定要求出布尔值,任何表达式都可以,他们将按照AS数据类型的自动转换规则来进行转换。→P171
★26:条件语句,当只有一个语句的时候,可省去{},如下:if (x==y) trace("y");→P177
★27:条件表达式不一定要求出布尔值,任何表达式都可以,但是此表达式的结果将按照FLASH数据类型的自动转换规则转换为布尔值。→P189
★28:在FLASH PLAYER 5 中,循环被限制在15秒内。→P189
★29:当执行任一贞的脚本时,影片场景在视觉上要等到脚本结束才能够更新。→P191
★30:enterFrame事件处理器一旦开始就无法停止,惟一的办法就是删除此影片剪辑。→P193
★31:可以用空白关键贞以及attachMovie()和removeMovieClip()有效控制影片剪辑enterFrame循环事件的开始和结束。→P194
★32:函数变元(即传递给函数的实际参数)在传递给函数前就被先求值。→P203
★33:在同一贞的代码中,函数可以在被声名前调用。→P208
★34:函数会先在局部作用域中查找变量,如果没有找到,就会在其所在的时间线或所属对象与类中查找,如果还没有找到,则返回undefined。→P209
★35:当局域变量在函数的结尾死亡时,和他们对应的存储器空间就会被释放。因此使用局域变量存储所有的临时值,就能在程序中避免存储器的浪费。→P212
★36:形式参数和实际参数的数目可以不等。→P213
★37:传递给函数的参数可以用arguments对象访问。→P213
★38:对于原始数据类型的参数,函数接受到的是数据的拷贝,而复合数据类型的参数,函数接受到的则是一个指针,指向原数据。→P215
★39:从理论上说,函数应该是一种特殊的对象。→P220
★40:当播放头进到某贞后,先执行代码,然后更新屏幕,并播放声音。→P227
★41:当我们为剪辑添加事件处理器的时候,处理器中定义的变量,其作用域将在此剪辑的时间线上,内部的this将指向当前的剪辑。→P234
★42:按扭处理器的作用域是按扭所在的时间线(注意:不是按扭本身),其内部的this将指向它所在的时间线上。→P237
★43:一个MC的内容被unLoadMovie()函数卸载后,马上就会有一个空的占位符MC被载入到该MC中。所以,一个unLoadMovie()事件必将导致一个loadMovie()事件的发生;反之亦然。→P245
★44:影片剪辑的用户输入事件会被所有的MC以及_root所接受,并做出响应的反应。→P250
★45:影片剪辑事件处理器具有记忆特性,事件的每次发生都会记录在贞中间,并在每一贞得到渲染时,在屏幕中显示出来。如果想让渲染在事件的每次发生时都即时进行,以让渲染能平滑进行,可以使用updateAfterEvent()函数,但按扭事件不能用此函数。→P259
★46:数组可以有空元素,这样的数组成为稀疏数组。→P266
★47:delete操作符可以删除一个命名数组元素,并释放内存。语法:delete arrayName.elementName;→P274
★48:FLASH 5只支持一维数组。→P289
★49:方法其实就是实现对象行为的函数。→P293
★50:在单纯的OOP中,一般不直接访问对象的属性,而是调用方法来访问属性的值。→P297
★51:在每一个对象里重复地复制相同的函数时,会造成存储器的浪费。→P302
★52:传统上,类构造器的首字母大写。→P303
★53:在FLASH 5中,类的方法可以在类构造器外定义。→P306
★54:函数同时也是对象,可以带属性。创建构造器函数的时候,解释程序会自动赋值一个称为原型(prototype)的属性。→P308
★55:_ _proto_ _属性主要用来查找对象继承属性,也即对象的prototype属性。此属性是在任何对象被创建的时候,解释程序自动赋给它的属性。→P311
★56:内置对象在FLASH播放器启动的时候,会自动由解释程序创建,并在影片播放的过程中保持有效。→P319
★57:影片剪辑中的一个变量就是它的一个属性。→P321
★58:一般把FLASH文档里的主影片叫作主影片时间线或_root。一个.swf文件可以从播放器中删除,但一个主影片却不能从.swf文件中删除。duplicateMovieClip(),removeMovieClip(),swapDepths()方法用在主影片上是无效的。另外,FLASH播放器可以包含多个.swf文件,但每一个.swf文件只能包含一个主影片。→P324
★59:在希望保留剪辑的事件处理器和复制过程中的转换的时候,要使用duplicateMovieClip(),而不是attachMovie()。如果一定要使用attachMovie()的话,可以将事件处理器中的代码改用函数直接量的方式写在此剪辑中。→P325
★60:每一个剪辑实例的名称都可以用剪辑内置属性_name来访问和设置。→P330
★61:如果手动创建的MC没有命名,它将在运行的时候,由播放器自动赋给一个类似instance1,instance2……instancen之类的名称,但n到底是几,我们无法控制。→P331
★62:loadMovie()函数会在语句块儿中最后执行,所以,不能在同一个语句块儿中,访问被加载的外部影片的属性和方法。→P332
★63:不能从一个文档的库中添加剪辑到其它文档。所以,当一个剪辑中加载了一个外部.swf文件后,就不能对此剪辑使用duplicateMovieClip()和attachMovie()方法了。→P333
★64:剪辑深度值有间隙不会造成存储器的浪费。→P337
★65:装载新的.swf到_level2上,会在视觉上覆盖_level1上的影片,但不会把它从播放器中删除。→P337
★66:unloadMovie()将删除剪辑的内容和自定义属性与函数,但不删除内置属性与方法还有剪辑本身。要完全删除,可以使用removeMovieClip()函数。→P354
★67:在unloadMovie()函数中,如果使用了一个不存在的剪辑或层级作为它的参数,那么调用此函数的剪辑本身将被卸载。→P354
★68:全局函数和剪辑方法在表面上看一样,但它们在本质上完全不同,比如unloadMovie()等。→P359
★69:原始数据按值传递,复合数据按地址传递。→P379
★70:
x=[1,2,3];
y=[1,2,3];
trace(x==y); //得到false
x=y;
trace(x==y); //得到true
复合数据比较的是引用,而不是值。→P381
★71:原始变量作为参数传递给函数时,函数内对数据的任何操作都不会影响原来的变量,而复合变量则会受到影响。→P382
★72:影片剪辑和对象在播放器中的实现是不同的,相互分开的,主要原因是它们被分配和解除分配的方式不同!→P397
★73:被旋转或遮盖的文本域内容不会显示在屏幕上,除非它的字体是嵌入的。→P437
★74:scroll属性表示当前显示在文本域中最顶端的行数。→P438
★75:未定义的文本域出现在屏幕上,但包含的值为undefined不会被for-in语句列举出来。→P450

★分母为0时:
→若分子为0或非数字串,则结果为NaN:
trace(0/0); //NaN
trace("a"/0); //NaN
→若分子为正数,则结果为Infinity:
trace(1/0); //Infinity
→若分子为负数,则结果为-Infinity:
trace(-1/0); //-Infinity
★分子为Infinity时:
→若分母为Infinity,-Infinity,则结果为NaN:
trace(Infinity/Infinity); //NaN
trace(Infinity/-Infinity); //NaN
→若分母为0、有限正数或非数字串,则结果为Infinity:
trace(Infinity/0); //Infinity
trace(Infinity/1); //Infinity
trace(Infinity/10000); //Infinity
trace(Infinity/"a"); //Infinity
→若分母为负有限数,则结果为-Infinity:
trace(Infinity/-100); //-Infinity
★分子为-Infinity时:结果跟Infinity相反。
★分母为Infinity时:
→若分子为数字,则结果为0:
trace(0/Infinity); //0
trace(1/Infinity); //0
trace(-23/Infinity); //0
→若分子为非数字串,则结果为NaN:
trace("sdf"/Infinity); //NaN
★注意:如果分子分母中有数字串,则此串会被转换成相应的数字再进行运算:
trace("1"/0); //NaN
trace(Infinity/"8"); //Infinity
trace(Infinity/"-8"); //-Infinity
trace("-23"/Infinity); //"23"会先转换成23,结果还是0
FLASH中的堆栈结构及影片剪辑深度概念剖析

★FLASH中的堆栈结构其实可以分成三大类:.swf文档中的_level堆栈→_level中的层堆栈和程序化堆栈。这三大类相互影响,相互关联。
●.swf文档堆栈:它是一个独立的单元,位于_level(n+1)上的内容在视觉上会永远遮挡位于_leveln上的内容,也就是说,_level(n+1)在.swf文档堆栈中的位置高于_leveln。.swf文档堆栈又包含了在它们中手动创建的层堆栈和程序化生成的堆栈。

●手动创建的层堆栈:它包括两类,一类是时间轴图层面板上中的层堆栈,它们在视觉上是显而易见的。上层的内容在视觉上遮挡下层的内容。但是有一点必须说明,就算两个剪辑位于不同的层,依然可以用swapDepths()方法对它们的深度进行交换,并在视觉上反映出来。另一类是在图层面板中,同一图层中不同深度的堆栈,它们在视觉上更直观,视觉上靠上的,说明它的深度值就大。我们可以通过“修改”→“排列”手动的调节它们的深度。最后需要说明的是:其实两类同属于.swf文档的内部层堆栈,可以通过swapDepths()方法交换它们的深度。

●程序化堆栈主要也分两类,一类是用duplicateMovieClip()生成的堆栈,另一类是用attachMovie()生成的堆栈。其实每一个剪辑都又包含自己的一个小栈。用duplicateMovieClip()方法复制出的子剪辑被放到和父剪辑同级的堆栈中,而用attachMovie()复制的子剪辑,则会被放到父剪辑的堆栈中,变成从属关系。请看下面的例子:
我们在_root主时间线上建立两层和两个剪辑shang和xia,shang位于上层,xia在下层,并在库中建立一个连接标识符为“ku”的剪辑。然后在主时间线上运行下面的代码:
shang.duplicateMovieClip("dshang",1);
xia.duplicateMovieClip("dxia",2);
shang.attachMovie("ku","ashang",100);
xia.attachMovie("ku","axia",2);
运行后,所有的影片剪辑在视觉上按从上到下的排列结果是:
"dxia"
//dxia的深度为2,最高
"dshang"
//dshang深度为1,其次
"ashang"
//ashang的深度值尽管为100,但他隶属于shang,而shang又低于同级的dxia和dshang,所以,ashang只能排第三
"shang"
//shang和ashang同级,但它的深度值小于ashang
"axia"
//axia和xia同级,但在xia上
"xia"
//xia在axia的下面(具体原因我将在“影片剪辑深度大揭谜”中详细说明


★下面这个是总结《ActionScript 2.0与RIA应用程序开发》中的几段,由于跟上面的讲解联系比较紧密,也顺便发上来吧。
★细心的朋友也许会发现,在我们用duplicateMovieClip()来复制影片剪辑的时候,好象复制出来的剪辑总会在原剪辑的上面。果真如此吗?呵呵:)其实我们都被FLASH蒙了!——暂时把这个问题放下,我们先来揭开FLASH深度的神秘面纱。其实,在FLASH中,深度共划分为三个区域:
●时间轴区(-16384→-1),这里主要用于放置在FLASH中,手动创建的图象、影片剪辑、按钮等,此区域中的剪辑不可以用AS删除,但可以用AS动态的创建剪辑到这里。其实-16384就是_root的深度值,我们可以用trace(_root.getDapth())获得。
●动态区(0→1048575),这里允许AS动态的创建和删除影片剪辑。
●保留区(1048576→2130690045),这里允许用AS动态的创建剪辑,但创建后无法删除。
●超出以上三区后,就无法再用duplicateMovieClip()和attachMovie()动态创建剪辑了,但仍可以用createEmptyMovieClip()动态创建,只是创建后,也无法删除。
●除了动态区,其它区的剪辑都无法删除,但我们可以先用swapDepths()把要删除的剪辑交换到动态区,然后再删除。
现在我们明白为什么我一开始说我们被蒙了吧?因为我们在用duplicateMovieClip()创建剪辑的时候,习惯上都喜欢把深度值设置为正数,而原剪辑由于是手动创建的,位于深度值为负值的时间轴区,所以肯定会比复制出的剪辑靠下。如果我们复制时把深度值设置的足够小(最小不能小于-16384),它就有可能位于原剪辑的下面。
flash中的代码执行顺序

★有时候我们声明的变量莫名其妙的找不到了,或者有些代码莫名其妙的不工作了,这就很有可能是你没有把握好代码的执行顺序,也许下面的两篇文章能帮你找到答案!

由于这篇文章需要用到图示说明,直接贴在这里不方便,我就提供两个原文链接吧。
●影片剪辑事件处理器的代码执行顺序:http://www.huoshan.org/houtai/blogv3/wenzhanghtm.asp?id_flash=26
●不同贞、层、深度及时间线上的代码执行顺序:http://www.huoshan.org/houtai/blogv3/wenzhanghtm.asp?id_flash=27
MovieClipLoader类内核测试(我又一次失望了!)
众所周知,影片剪辑可以用来载入外部变量和.swf文件。当用它来载入外部变量的时候,必须等到请求的变量完全载入才会触发data事件;而用它来载入外部.swf文件的时候,每接收到一部分外部.swf文件,都会触发一次data事件。今天主要讨论后者。
关键问题在于”一部分“三个字,这一部分到底指多少?度量单位又是什么?是字节?还是贞?答案是后者!其实,外部.swf文件只有在载入一个贞的时候,才有可能触发data事件,至于data事件被触发的准确次数则依赖于所装载的.swf文件每贞内容分布及网络连接速度。一个单贞的.swf文件,不管有多大,都只能引发一次data事件;一个100贞的.swf文件则最多可能触发100次data事件。如果贞数太多而连接很慢,就会触发更多的data事件,而如果贞数不多,连接速度却很快,触发的data事件就可能少一些。
知道了这个原理,我们就不难理解为什么用getBytesTotal()和getBytesLoad()制作出的预装载器会出现数字跳跃现象了!首先尽管getBytesLoad()获取的是字节数,但data事件的触发并不是以字节为单位的。然后,预装载器的数字更新还跟承载影片剪辑的贞速率有关系,因为现在的预转载器基本都是用两贞之间循环或enterFrame事件制作的。举个例子,假如你有一个100贞的.swf,承载影片剪辑的贞速率是每秒1贞,如果外部.swf在一秒钟传输完毕,则它只能触发一次data事件;如果两秒传输完毕,则触发两次;如果十秒传输完毕,则触发十次;如果一百秒传输完毕,则触发一百次。但它最多只能触发一百次data事件,就算用90897秒才传输完毕!上面例子的前提是:外部.swf文件每贞的内容分布均匀!如果它百分之九十的内容都集中在最后一贞,共需要十秒传输完毕,可想,预装载器在第一秒会显示10%,而在其后的八秒,都将停止在10%上,因为这期间外部.swf的最后一贞迟迟不能完全装载近来,也就无法触发承载影片剪辑的data事件,让数字更新。然后到了第十秒,加载数字会一下从10%突然跳到100%!!
→参考《ActionScript权威指南》第247页
→2005.11.29

补充,AS2.0又出来了个MovieClipLoader类,我以为它能真正基于字节了,谁料经过测试后,发现它依然是基于贞的DATA事件的,看来它和loadMovie的技术内核是一样的,又一次失望了。下面是我的测试。
★前期任务:
1:在一个文件夹下预先放一个体积稍微大点的用来被加载的外部SWF,命名为waibu.swf。
2:然后在此文件夹下新建一个.fla文件,用FLASHMX 2004以上打开进行编辑。
3:先在主场景靠边放一个TextArea组件,命名为“wenben”,最好把它拉的长一点,方便查看测试数据。然后在贞上如下代码:
//创建一个空的用来承载外部.swf的剪辑
_root.createEmptyMovieClip("chengzai_mc", 100000);
//创建MCL类的一个实例,并注册侦听器
var mcLoader = new MovieClipLoader();
var mcListener = new Object();
mcLoader.addListener(mcListener);
//加载子站
mcLoader.loadClip("waibu.swf", "chengzai_mc");
//开始加载
mcListener.onLoadStart = function(lujing) {
wenben.text = "开始加载!";
};
//加载过程中,我们在“wenben”组件里记录当外部SWF每次被加载进来的字节数据
mcListener.onLoadProgress = function(lujing, bytesLoaded, bytesTotal) {
var zijie = bytesLoaded+"/"+bytesTotal+"〈br〉";
wenben.text += zijie;
};
//加载完成
mcListener.onLoadInit = function(lujing) {
wenben.text += "加载完成!";
};
★测试过程:
1:我们先将贞频设置成12,然后用56K网络环境模拟下载,记录下“wenben”组件里的数据。
2:我们再将贞频设置成12*4,也就是48,同样的网络环境下测试,然后再记录下“wenben”组件里的数据。
●下面我们来看第1次的下载数据:
开始加载!
523/174474
1046/174474
1574/174474
2097/174474
2625/174474
3148/174474
3671/174474
……
加载完成!
●再来看第2次的数据:
开始加载!
153/174474
301/174474
449/174474
597/174474
750/174474
898/174474
1046/174474
……
加载完成!
★数据分析:
对比上面两组数据我们便可以看出,由于第二次的贞频是第一次的4倍,那么第二次每次onLoadProgress进来的字节数也差不多是第一次的四分之一(为什么会少点,目前还不太清楚),看来onLoadProgress和以前一样,还是基于贞的DATA事件的,贞频越快,DATA事件触发的频率就越高,那么刷新出来的数据就越细致,如果反应到我们的loading条上的话,就是增长的越平滑,反之亦然。所以如果想让我们的loading条平滑的话,除了让我们的外部SWF贞中的内容分布均匀,还可以让贞频高点。不过如果以前真如《ActionScript权威指南》中所说,那么现在MovieClipLoader类的onLoadProgress还是有可取之处的,至少它不再受外部SWF贞中内容分布影响,它只受主场景第一贞内容和主SWF贞频的影响。
局域变量和函数作用域链

★局域变量:在函数局部作用域中赋值的变量称为局域变量。包括函数参数和在函数中用var声明的变量。它们只当函数被调用的时候才存在,一旦函数结束,它们也随即被内存释放。然而在函数内部同样可以创建和修改时间线变量,只要省略var关键字就行了。下面举一个例子,看如下代码:
1:var x = 5; //声明时间线变量x,其值为5
2:function shiyan() {
3: x = 10; //将时间线变量x的值改为10
4: y = 20; //声明时间线变量y,其值为10
5: var z = 30; //声明局域变量z,其值为30
6: trace(x+"/"+y+"/"+z);
7:}
8:shiyan(); //调用函数,输出10/20/30
9:trace(x); //x在函数中被修改,输出10
10:trace(y); //y为时间线变量,输出20
11:trace(z); //z是局域变量,所以输出undefined
说明:在以上代码中,如果将第3行修改为var x=10;则第8行输出结果不变,第9行变为5。如果去掉第3行的函数调用语句,则第9行同样会变成5,10和11都将输出undefined,因为函数只有被调用后,其中的代码才会被执行。

★函数作用域链包含三个方面:1,函数局部作用域;2,包含该函数的时间线作用域;3,对象和类中函数的作用域。
●1,函数局部作用域:当函数运行的时候,会先在局部作用中寻找变量,但如果找不到的话,就会延伸到函数所在的时间线或对象上。如下例:
var a="feijuyu";
function shiyan(){
trace(a);
}
shiyan();
虽然函数内并没有声明变量a,但它依旧会输出feijuyu 。
再看下面的代码:
var a = "feijuyu";
function shiyan(a) {
trace(a);
}
shiyan("juyu");
虽然时间线上有变量a,但函数会优先考虑局部变量,所以输出juyu。

●2,包含函数的时间线作用域:函数的时间线作用域是按照函数的声明语句位置来决定的,而不是按照函数的调用语句位置。也就是说,函数体内代码的作用域在包含该函数声明的时间线上,而不在包含函数调用语句的时间线上。看下面的例子:
我们先在_root时间线上建立两个名为“zuo”和“you”的剪辑。
在名为“zuo”的剪辑上写代码:
function shiyan(a) {
_rotation+=a;
}
然后在名为“you”的剪辑上写代码:
_root.zuo.shiyan(30);
最后的结果会怎样呢?到底是谁旋转了30度?答案是“zuo”,因为函数是在“zuo”中声明的,尽管它在“you”上才调用。

现在,我们再把“左”中的代码改为:function shiyan(a) { _root._rotation+=a; },这次的结果是正个影片都旋转了30度。由次可见,在函数语句中使用点语法,就可以走出函数作用域了。

其实我们想在函数中操作操作任意剪辑的旋转并非难事,只需把“zuo”的代码改成如下形式:
function shiyan(clip,a) {
clip._rotation+=a;
}
以后在调用此函数的时候,只需要把对应的“clip”参数赋值为要旋转的影片剪辑绝对路径就可以了。

在FLASH5中还存在一种特殊情况。当函数被赋给变量时,函数的作用域将离开当前时间线,而跟变量所在时间线保持一致。看下面“zuo”剪辑中的代码:
var a=30;
function shiyan() {
_rotation+=a;
}
_root.you.a=180;
_root.you.xuanzhuan=shiyan;
_root.you.xuanzhuan();
运行的结果是剪辑“you”旋转了180度。因为我们把函数shiyan赋给了剪辑“you”的变量xuanzhuan,函数作用域也就响应变成了隶属于“you”,结果它获得的a值将是“you”中180度,而非原时间线中的30度了。
其实这跟JS以及ECMA-262标准是相违背的,幸好在FLASH6和AS2.0中都不再存在此问题了。

另外,此例还有一个很重要的复产物,就是无论怎样调整加载顺序,只要两个剪辑位于一同贞号上,“zuo”中的代码都能被执行,于是我猜,FLASH在运行的时候可能是先把此贞号上所有影片剪辑的名字写进了内存,以备代码应用,然后才按照我之前讨论过的代码执行循序执行不同贞、层、深度和时间线中的代码。不然的话,如果先加载剪辑“zuo”的话,“you”还没被解释,在剪辑“zuo”中,又如何给“you”赋值,并操作它,使它旋转180度呢?然而,如果“you”剪辑在“zuo”剪辑之后的贞中才出现,那么上面的代码就会失效。看来,这个理论确实仅限于同一时间线,同一贞号的情况下。

●3,对象中函数的作用域:对象方法的作用域则是固定的,看下面代码:
var a=30;
function shiyan(){
trace(a);
}
var duixiang=new Object(); //创建对象
duixiang.xuanzhuan=shiyan; //将函数赋给对象的方法
duixiang.a=180; //设置对象属性
duixiang.xuanzhuan(); //输出30,而非180
因为将一个函数赋给对象的方法或属性时,函数的作用域将固定在函数声明的时间线上,在本例中,也是就说,函数xuanzhuan的作用域将和shiyan保持一致。不管在FLASH5还是FLASH6和AS2.0都是一样的。
for-in循环

★总体说明:for-in语句主要用来罗列对象属性的循环方式。它并不需要明确的更新语句,因为循环重复数是对象属性的数目决定的。它的语法如下:
for (var shuxing in object){
yuju; //语句要按照某种方式明显地使用shuxing
}
yuju对于object的每一个属性只执行一次,object是任何有效对象的名称,shuxing是任意的变量名或标识符。在每一次循环过程中,shuxing用来临时保存一个串,这个串正是当前所列举对象属性的名称。串值可以在每一次循环期间被用来访问和操作当前的属性。需要注意三点!第一:for-in循环中所检查的对象属性并不是按照可预测的顺序来进行的;第二:它只能列举用户自定义对象的属性,包括任何继承属性,但内置对象的一些属性以及它的方法就不会被列举;第三:for-in循环不能列举出未定义,也就是没有默认值的文本域。下面通过四个例子来详细显示它的用法:
●1,列举自定义对象属性:
var ball=new Object();
ball.radius=12;
ball.color="red";
ball.alpha=100;
for (var shuxing in ball){
trace("ball."+shuxing+" is "+ball[shuxing]);
}
输出结果如下:
ball.alpha is 100
ball.color is red
ball.radius is 12

●2,列举内置对象属性:
for (var shuxing in Key){
trace("Key."+shuxing+" is "+Key[shuxing]);
}
因为for-in循环不能列举内置Key对象的属性和方法,所以无任何输出结果。

●3,列举数组元素:
var shuzu=[12,"dsf",45];
for (var yuansu in shuzu){
trace("shuzu."+yuansu+" is "+shuzu[yuansu]);
}
输出结果为:
shuzu.2 is 45
shuzu.1 is dsf
shuzu.0 is 12

●4,列举给定时间线(_root)内所有剪辑:先在主时间线上放三个影片剪辑“mc1”,“mc2”,“mc3”。然后写如下代码:
for (var shuxing in _root) {
if (typeof _root[shuxing] == "movieclip") {
trace(_root[shuxing]._name);
}
}
输出结果为:
mc3
mc2
mc1

●5,寻找给定时间线(_root)内的动态或输入文本域:先在主时间线上放三个空文本域,并依次把它们的变量名字设置为:“bianliang1”,“bianliang2”,“bianliang3”。然后写如下代码:
for (var shuxing in _root) {
trace(_root[shuxing]);
}
输出结果为:
WIN 7,0,14,0
_level0.instance1
_level0.instance2
_level0.instance3
第一行为$version对象的值,也就是播放器的版本号,后三行均为三个未命名文本域的名字,只不过这个名字是FLASH自动分配的。但是for-in循环并没有找到三个文本域的值,尽管它们都为空值:""。如果想找到它们,就必须手动或程序化的初始化它们,并且程序化的初始化时,甚至可以把它们的值设置为0。看如下代码:
bianliang1 = "sdf";
bianliang2= "";
bianliang3 = 234;
for (var shuxing in _root) {
trace( _root[shuxing]);
}
输出结果为:
234
//bianliang2在这里显示为一个空行
sdf
WIN 7,0,14,0
_level0.instance1
_level0.instance2
_level0.instance3
数据类型自动转换的规则

数据类型自动转换,是弱语言的一种特点,尽管现在AS越来越趋向一门强制类型语言,但作为一个优秀的AS程序员,能灵活运用数据类型自动转换,也是一项基本工,今天先把这个规则贴出来。


原始数据类型→AS1.0转换结果→AS2.0转换结果
★其他类型转换为数字类型:
undefined→0→NaN
null→0→NaN
布尔→true为1;false为0→同AS1.0
数字串→相应的数字值→同AS1.0
非数字串→NaN→同AS1.0
"Infinity"→NaN→同AS1.0
"-Infinity"→NaN→同AS1.0
"NaN"→NaN→同AS1.0
数组→NaN→同AS1.0
对象→NaN→同AS1.0
影片剪辑→NaN→同AS1.0

★其他类型转换为串类型:
undefined→空串→”undefined“
null→"null"→同AS1.0
布尔→true为"true";false为"false"→同AS1.0
NaN→"NaN"→同AS1.0
0→"0"→同AS1.0
Infinity→"Infinity"→同AS1.0
-Infinity→"-Infinity"→同AS1.0
一般数字→外观一样的串→同AS1.0
数组→以一个逗号分隔的元素值列表→同AS1.0
对象→toString()方法得到的结果值→同AS1.0
影片剪辑→影片剪辑的绝对路径→同AS1.0

★其他类型转换为布尔类型:
undefined→false→同AS1.0
null→false→同AS1.0
NaN→false→同AS1.0
0→false→同AS1.0
Infinity→true→同AS1.0
-Infinity→true→同AS1.0
一般数字→true→同AS1.0
非空串→非0数字串为true;否则为false→都为true
空串→false→同AS1.0
数组→true→同AS1.0
对象→true→同AS1.0
影片剪辑→true→同AS1.0
数据类型自动转换的规则

数据类型自动转换,是弱语言的一种特点,尽管现在AS越来越趋向一门强制类型语言,但作为一个优秀的AS程序员,能灵活运用数据类型自动转换,也是一项基本工,今天先把这个规则贴出来。


原始数据类型→AS1.0转换结果→AS2.0转换结果
★其他类型转换为数字类型:
undefined→0→NaN
null→0→NaN
布尔→true为1;false为0→同AS1.0
数字串→相应的数字值→同AS1.0
非数字串→NaN→同AS1.0
"Infinity"→NaN→同AS1.0
"-Infinity"→NaN→同AS1.0
"NaN"→NaN→同AS1.0
数组→NaN→同AS1.0
对象→NaN→同AS1.0
影片剪辑→NaN→同AS1.0

★其他类型转换为串类型:
undefined→空串→”undefined“
null→"null"→同AS1.0
布尔→true为"true";false为"false"→同AS1.0
NaN→"NaN"→同AS1.0
0→"0"→同AS1.0
Infinity→"Infinity"→同AS1.0
-Infinity→"-Infinity"→同AS1.0
一般数字→外观一样的串→同AS1.0
数组→以一个逗号分隔的元素值列表→同AS1.0
对象→toString()方法得到的结果值→同AS1.0
影片剪辑→影片剪辑的绝对路径→同AS1.0

★其他类型转换为布尔类型:
undefined→false→同AS1.0
null→false→同AS1.0
NaN→false→同AS1.0
0→false→同AS1.0
Infinity→true→同AS1.0
-Infinity→true→同AS1.0
一般数字→true→同AS1.0
非空串→非0数字串为true;否则为false→都为true
空串→false→同AS1.0
数组→true→同AS1.0
对象→true→同AS1.0
影片剪辑→true→同AS1.0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值