关于ActionScript 3.0对象的赋值与引用的对比

as3的值和引用这两者比较有关系的是“赋值”和“函数传参”两个行为,期间又需要分“基元类型”和“对象”来讨论。

我们知道Flash as语言中所有的数据类型都继承自Object,包括基元数据类型,但是在值和引用操作时它们的确需要区别对待。

我们将基元数据类型称为“非结构对象”,与之对应的其他Object称为“结构对象”。

下面将进行几种实验,结论大概就是

1、 基元数据类型按照值操作,代表基元数据的非结构对象也是按照值操作的。

2、 结构对象一般按照“引用”操作,但需要注意交换赋值的情况

3、 As3中的“引用”操作其实不是真正意义上的引用,只是类似于“指针”传递的一种伪“引用”。As3中所有操作底层意义都是值操作,只不过针对结构对象时是“指针”值的值操作。

4、 As3中的函数传参,对基元类型相当于新副本的值操作。对结构对象,相当于“指针”值新副本的值操作。

5、 必要的时候使用深层次拷贝操作,特别是在多层次框架结构中。

=================

基元类型(包括 Boolean、Number、int、uint 和 String)

赋值:按照值操作。

var a:int=3;

var b:int=a;

b=6;

trace(a,b);// 3 6 即 b的改变不会带来a的改变

函数传参:按照值操作

var a:int=3;

function f1(b:int):void{

    b=6;

}

f1(a);

trace(a);//3 即在函数内部生成了新副本,其变化不会带来a的改变

与前面的赋值操作是等价一致的

=================

对象Object

赋值:按照引用操作

var a:Object={x:1,y:2};

var b:Object=a;

b.x=6;

trace(a.x);//6 即 b的改变会带来a的改变

—-下面模拟复杂对象赋值—

var c:Object={i:10,j:11}

var a:Object={x:1,y:c};

var d:Object=a.y;

var b:Object=a;

d.i=6;

trace(a.y.i);//6

trace(b.y.i);//6 这里需要格外注意,as3的引用行为是无孔不入的,自定义对象的子对象遭遇引用操作,特别是多层架构中,隐蔽的引用操作会带来意想不到的问题。

函数传参:结构对象按引用操作;代表基元类型的非结构对象,按值操作

var a:Object={x:3};

function f1(b:Object):void{

    b.x=6;

}

f1(a);

trace(a.x);//6 一如既往的引用操作,但请注意下面

—–代表基元类型的对象—-

var a:Object=Object(3);

function f1(b:Object):void{

    b=6;

}

f1(a);

trace(a);//3 如果Object代表基元类型,那则按值来操作

=============================

貌似到这里关于as3的值和引用归类总结已经结束了,其实不是的。

看下面一段代码。

var a:Object={x:1};

var b:Object={x:4};

var c:Object;

c=a;

a=b;

b=c;

trace(a.x,b.x);

结果不出意外的是 4 1 ,我们继续看下面代码

var a:Object={x:1};

var b:Object={x:4};

function swapObj(i:Object,j:Object):void

{

         var k:Object;

         k=i;

         i=j;

         j=k;

}

swapObj (a,b);

trace(a.x,b.x);

结果是什么呢?却不是我们想的 4 1,而是 1 4

这里发生了什么故事,我们继续试验

var a:Object={x:1};

var b:Object={x:4};

function swapArr(i:Object,j:Object):void

{

         var k:Object;

         k=i;

         k.x+=10;

         trace(k.x,a.x,b.x,i.x,j.x);

         i=j;

         trace(k.x,a.x,b.x,i.x,j.x);

         j=k;

         trace(k.x,a.x,b.x,i.x,j.x);

}

swapArr(a,b);

trace(a.x,b.x);

————————

11 11 4 11 4

11 11 4 4 4

11 11 4 4 11

11 4

看起来很让人头疼,我直接画图摆结论吧,as3所谓的引用操作过程中只是指针值的操作,并不是真的引用。
至此,as3值和引用操作真正有价值的东西才算讲了一点点。

我们再来看看下面这个函数:

function swap(i:Object,j:Object):void
{
	i.x^=j.x;
	j.x^=i.x;
	i.x^=j.x;
	trace(i.x,j.x);
}
swap(a,b);//4,11
trace(a.x,b.x);//4,11

跟前述情况一样,实现了交换。

要善用函数返回值,不要想当然的把对象传进去就认为函数自己会按照引用操作去完美的工作。

遇到可能出现这种问题的情况,要善用深层次拷贝。

比如比较常用的Array,默认并没有提供clone函数,那就按照如下操作进行深层次拷贝,来保证代码流转过程中的逻辑正确和减少未知引用关联。

import Flash.utils.ByteArray;

function clone(source:Object):*

{

    var myBA:ByteArray = new ByteArray();

    myBA.writeObject(source);

    myBA.position = 0;

    return(myBA.readObject());

}


文章来源:http://as3.aa-a.net/index.php/as3-object-assignment-references.html

你可能感兴趣的:(Actionscript)