首页 > 代码库 > AS3 技巧札记
AS3 技巧札记
一、数据类型
1.Number
Number初值为NaN(Not a Number)
NaN与所有数字的运算结果都是NaN
所以计算时或判断时务必记得给Number赋初始值
trace(100+NaN); //NaN
trace(0==NaN); //false
trace(0!=NaN); //true
trace(NaN==NaN); //false
2.BitmapData
BitmapData只要引用都断开就会被回收,不需要执行dispose()方法。
测试过程中发现本机调试版的FP无法内存回收,要用网页的版本才行
3.Array/Vector
二、运算符
等于
null undefined //true
true == 1 //truevar a:Array = [1, 2, 3];
var b:Array = [1, 2, 3];
trace(a == b); //false 复杂数据类型将基于引用而非值进行比较var a:Array = [1, 2, 3];
var b:Array = a;
trace(a == b); //true= 严格等于
1 = true //false
null == undefined //false||= 逻辑或
function XX(obj:Object):void
{obj ||= new Object();
}
//等价于下面代码作用
function XX(obj:Object):void
{if(obj === null)
{
obj = new Object();
}
}&&= 逻辑与
function toHTMLTag (s:String):String
{
s &&= “<” + s + “>”;
return s;
}
//若传入值为undefined,返回结果为null
function toHTMLTag (s:String):String
{
if (s !== null && (s.length > 0))s = "<" + s + ">";
return s;
}as 转换一个值的数据类型,如果转换失败则返回null
2 as String //null
“2” as String // “2”
String(2) // “2”is 检查一个值的数据类型
var s:Sprite = new Sprite();
s is Sprite //true
s is DisplayObject //true
s is MovieClip //false
s instanceof Sprite //true
已不再使用instanceof运算符,请改用 is
:: 名称限定符(检查一个对象的命名空间)
public namespace Dutch;
public namespace French;
Dutch function hello():String
{return "hallo";
}
French function hello():String
{return "bonjour";
}
trace(Dutch::hello()); //“hallo”
trace(French::hello()); //“bonjour”public, private, protected, internal,这些也都是命名空间
in 检查一个对象是否带有指定属性
“CASEINSENSITIVE” in Array // true
“CASEINSENSITIVE” in [] // false
“length” in Array // true
“length” in [] // true[].hasOwnProperty(“length”) //true
[].hasOwnProperty(“CASEINSENSITIVE”) //falsearguments 一个带有所有传递进来的参数的数组,任何方法中都可用(在CS6中使用好像是报错的)
function myFunction(…arguments) //相当于自定义了一个Array,只不过名称为arguments
{for(var i:uint=0; i<arguments.length; i++) { trace(arguments[i]); }
}
myFunction(1,2,3,4);//一个自定义类型参数 + 任意数量的不限类型参数
function myFunc(x:int,…rest)
{for(var i:uint=0; i<rest.length; i++) { trace(rest[i]); }
}
myFunc(1,2,3,4);
三。提示与技巧
1.创建对象
var a:Array = new Array();
var a:Array = []; //这样更快
var o:Object = new Object();var o:Object = {}; //这样更快var v:Vector.<String> = new Vector.<String>(); v.push("a");v.push("b");var v:Vector.<String> = new <String>["a", "b"];
2.引用对象
var a:Object = {};
a.name = “John”;
var b:Object = a;
b.name = “Elvis”;
trace(a.name); //输出为 “Elvis”
3.对象复制 基于场景创建深表复制和浅表复制
// 深表复制
private function clone(obj:Object):Object
{
var bytes:ByteArray = new ByteArray();
bytes.writeObject(obj);
bytes.position = 0;
return bytes.readObject();
}
4.事件 始终覆写事件子类的”clone”方法,以防止重调时发生强制转换错误
class MyEvent extends Event
{
public function MyEvent(data:Object)
{
_data = http://www.mamicode.com/data;
}
override public function clone():Event
{
return new MyEvent(_data);
}
}
- for…in / for each…in
var arr:Array = [“a”, “b”, “c”];
// 基于键[0]、[1]、[2]的循环
for ( var i in arr )
{
}trace( i );
// 基于值”a”、”b”、”c”的循环
for each ( var s:String in arr )
{
}trace( s );
6.循环标签 给循环贴上标签命名,在需要从嵌套循环中跳出时很有用
mainLoop:
for (var i:uint = 0; i<10; i)
{
for (var j:uint = 0; j<10; j)
{
if (i 5 && j 7)
break mainLoop;
}}
7.为内建类添加方法 通过使用prototype在继承内建类特性的同时加入新方法
Array.prototype.removeItem = function (item:*):void
{
var index:int = this.indexOf(item);
if (index > -1)
{
this.splice(index, 1);
}
};
var a:Array = [1, 2, 3];
a.removeItem(2);
trace(a); //1,3
8.显式转换/强制转换
var b:String = “2x”;
trace(Number(b)); //NaN
trace(b as Number); //null
trace(int(b)); //0
Boolean("true") // trueBoolean("false") // trueBoolean("") // falseBoolean(" ") // trueBoolean(null) // falseBoolean(undefined) // false
9.Date 类
public function Date(
yearOrTimevalue:Object,
month:Number, // 0 to 11
date:Number = 1, // 1 to 31
hour:Number = 0, // 0 to 23
minute:Number = 0, // 0 to 59
second:Number = 0, // 0 to 59
millisecond:Number = 0) // 0 to 999
10.抛出 除了错误还有其他东西可以抛出
class AwesomeParty {}
try
{
throw new AwesomeParty();
}
catch (party:AwesomeParty)
{
// go loose at moNo!
}
4.闭包函数
闭包是可以包含自由(未绑定)变量的代码块,这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。
闭包函数的创建是在整个父级函数执行完成之后,所以如果有for循环中创建的闭包函数,获取到的值都是for循环结束后最后的那个属性。每个闭包函数都是一样的,造成跟你的预计结果不同。
闭包函数中如果引用了所在类的变量,请不要使用this关键字。直接引用那个变量即可。因为闭包函数的this关键字的指向会随着调用者而改变。
5.MouseEnabled/MouseChildren
MouseEnabled和MouseChildren这两个属性默认都为true。
设置他们都只影响到一件事:显示对象能不能成为事件的target,也就是事件触发者。MouseChildren=false相当于一次将所有子对象的MouseEnabled属性置为flase。
设置一个显示对象的MouseEnabled属性为false,只是使它自身不能作为事件的触发者,但并不影响事件冒泡机制,所以若它的子对象被点击了,它也能监听到点击事件。
彻底禁用一个显示对象的鼠标事件的方法是将MouseEnabled和MouseChildren都设置为false。
6.内存回收
监听在loader上的事件一定要及时移除,因为loader跟stage一样属于根节点,如果它持有你的函数引用,将会导致你不能被回收。URLLoader没有这个问题。
同样的道理适用于stage和任何单例
内存泄露情况:
- 引用泄露:对子对象的引用,外部对本对象或子对象的引用都需要置null;
- 系统类泄露:使用了系统类而忘记做删除操作了,如BindingUtils.bindSetter(),ChangeWatcher.watch()函数时候完毕后需要调用ChangeWatcher.unwatch()函数来清除引用 ,否则使用此函数的对象将不会被删除;
类似的还有MUSIC,VIDEO,IMAGE,TIMER,EVENT,BINDING等。 - 效果泄露:当对组件应用效果Effect的时候,当本对象本删除时需要把本对象和子对象上的Effect动画停止掉,然后把Effect的target对象置null; 如果不停止掉动画直接把 Effect置null将不能正常移除对象。
- SWF泄露:要完全删除一个SWF要调用它的unload()方法并且把对象置null;
- 图片泄露:当Image对象使用完毕后要把source置null;(为测试);
- 声音、视频泄露: 当不需要一个音乐或视频是需要停止音乐,删除对象,引用置null;
内存泄露解决方法: - 在组件的REMOVED_FROM_STAGE事件回掉中做垃圾处理操作(移除所有对外引用(不管是VO还是组件的都需要删除),删除监听器,调用系统类的清除方法)
先remove再置null, 确保被remove或者removeAll后的对象在外部的引用全部释放干净; - 利用Flex的性能优化工具Profile来对项目进程进行监控,可知道历史创建过哪些对象,目前有哪些对象没有被删除,创建的数量,占用的内存比例和用量,创建过程等信息;
AS3 技巧札记