为什么AS3在for循环中创建新实例?

时间:2018-07-12 11:03:41

标签: arrays actionscript-3 movieclip

到目前为止,我已经从动作脚本中看到了最奇怪的行为,并且与AS合作已有10多年了。

var clip1:MovieCip = new MovieClip();  
var clip2:MovieCip = new MovieClip();  
var clip3:MovieCip = new MovieClip();    
var clip;

var myarray:Array = new Array(clip1, clip2, clip3);    

for each (clip in myarray)
{ removeChild(clip);
  clip = new mc();
  trace(clip.name); }

似乎很简单,对吧?由于某种原因,flash会将实例名称更改为instanceX,其中X是一些随机分配的数字,我再也无法通过其分配的名称来调用剪辑,例如,如果我尝试...

 clip1.x = 300;

flash不会引发错误,但是clip1.x不会移至300。我已经处理了几个小时,看来影片剪辑实际上仍然存在,但是flash创造了新的影片剪辑!请帮助

2 个答案:

答案 0 :(得分:4)

似乎您不了解成员名称和实例名称之间的区别。我假设您在时间轴上编写代码,这意味着您在该时间轴表示的 MovieClip 对象中进行操作(可能是主时间轴,在这种情况下,您将在根目录中进行操作)。

成员是一个OOP词,表示对象的字段(纯数据和对象引用)和方法(绑定函数)。您可以使用点符号或方括号符号来访问成员:

this['a'] = 10;
trace(this.a); // output: 10

在时间轴上编写代码时,在声明变量或函数时,实际上是在分别声明当前 MovieClip 的字段和方法:

var a:int = 10;

trace(a);         // output: 10
trace(this.a);    // output: 10
trace(this['a']); // output: 10

请记住,在函数体内声明的变量不是对象成员,而是局部函数变量:

function A():void
{
    var a:int = 999;

    trace(a);      // output: 999
    trace(this.a); // output: undefined
}

实例名称是 DisplayObject 类的类成员,位于“名称”名称下。

trace(name);         // output: instance123
trace(this.name);    // output: instance123
trace(this['name']); // output: instance123

与此有关的令人困惑的部分是,Flash会自动将预先设计好的内容声明为对象成员,并且其成员名称与实例名称相同。因此,如果您将一些 MovieClip 放入实例名称为 MC1 ,则可以按以下方式进行寻址:

trace(MC1);         // output: [object MovieCip]
trace(this.MC1);    // output: [object MovieCip]
trace(this['MC1']); // output: [object MovieCip]
trace(getChildByName("MC1"));      // output: [object MovieCip]
trace(this.getChildByName("MC1")); // output: [object MovieCip]

您可以在文件>发布设置> AS3设置>自动声明舞台实例中关闭自动声明选项。如果这样做,输出将不同:

trace(MC1);         // output: undefined
trace(this.MC1);    // output: undefined
trace(this['MC1']); // output: undefined
trace(getChildByName("MC1"));      // output: [object MovieCip]
trace(this.getChildByName("MC1")); // output: [object MovieCip]

此外,这种自动声明的方法起作用了,让我再强调一次,仅使用预先设计的内容。如果创建任何东西的新实例并将它们 addChild(...)都添加到容器中,它将不会自动将其引用添加为容器OOP成员。

然后,它如何影响您的问题。

您致电 clip1.x = 300; ,并且没有错误。当然没有。 clip1 成员仍然保留对最初声明和实例化的 var clip1:MovieCip = new MovieClip(); 的引用,并且您从未将任何内容重新分配给该成员。因此,您可以解决未附加任何内容的有效 MovieClip ,但这对AS3或Flash平台无关紧要:您正在对有效对象执行有效操作。

如果要处理新创建的实例,则应通过放置它们的数组或通过精心组织的实例名称或通过将其引用分配给各个成员名称的成员来实现:

var clip0:MovieCip = new MovieClip;
var clip1:MovieCip = new MovieClip;
var clip2:MovieCip = new MovieClip;
var clip3:MovieCip = new MovieClip;

var myarray:Array = new Array(clip0, clip1, clip2, clip3);

for (var i:int = 0; i < myarray.length; i++)
{
    // You better call the class MC, because lowercase
    // class name looks like a variable name.
    var aClip:MC = new MC;

    // Give it a proper instance name.
    aClip.name = "clip" + i;

    // Assign it as a member of current object.
    this["clip" + i] = aClip;

    // Put it to designated place into the Array.
    myarray[i] = aClip;
}

现在,您可以按任何需要的方式处理它:

trace(clip1);         // output: [object MC]
trace(this.clip1);    // output: [object MC]
trace(this['clip1']); // output: [object MC]
trace(myarray[1]);    // output: [object MC]
trace(getChildByName("clip1"));      // output: [object MC]
trace(this.getChildByName("clip1")); // output: [object MC]

答案 1 :(得分:3)

如果我对您的理解正确,那么您想替换循环中变量引用的三个MovieClip。这里的问题是,将新的MovieClip实例分配给clip变量不会更改或覆盖其引用的旧MovieClip。旧的空MovieClip仍然存在(即使它们已从舞台中删除),并且仍被分配给变量clip1clip2clip3

您可以像这样更新这些变量:

for each (clip in myarray) {
    removeChild(clip); 
    var newClip:MovieClip = new mc(); // create new MC
    this["clip" + i] = newClip; // set variables (e.g. clip1, clip2, ...)
}

如果您还想更新阵列,则可能需要执行以下操作:

for (var i:uint = 0; i < myarray.length; i++) {
    var clip:MovieClip = myarray[i];
    removeChild(clip); 
    var newClip:MovieClip = new mc(); // create new MC
    myarray[i] = newClip; // overwrite the old clip in the array
    this["clip" + i] = newClip; // set variables (e.g. clip1, clip2, ...)
}