Flash Actionscript 3-参考与价值

Flash Actionscript 3-参考与价值,flash,actionscript-3,reference,Flash,Actionscript 3,Reference,我以为我在AS3中找到了参考资料,但以下行为让我困惑: // declarations for named individual reference later on var myAmbientSound:Sound; var myAmbientSoundLocation:String = "http://ambient_sound_location"; var myPeriodicSound:Sound; var myPeriodicSoundLocation:String = "http:

我以为我在AS3中找到了参考资料,但以下行为让我困惑:

// declarations for named individual reference later on
var myAmbientSound:Sound;
var myAmbientSoundLocation:String = "http://ambient_sound_location";

var myPeriodicSound:Sound;
var myPeriodicSoundLocation:String = "http://periodic_sound_location";

var myOccasionalSound:Sound;
var myOccasionalSoundLocation:String = "http://occasional_sound_location";

// for iterating through initialization routines
var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound];
var mySoundLocation:Array = [myAmbientSoundLocation, myPeriodicSoundLocation, myOccasionalSoundLocation];

// iterate through the array and initialize
for(var i:int = 0; i < mySoundArray.length; i++) {
    mySoundArray[i] = new Sound();
    mySoundArray[i].load(new URLRequest(mySoundLocation[i]));
}
//稍后命名的单个引用的声明
var myAmbientSound:声音;
var myAmbientSoundLocation:字符串=”http://ambient_sound_location";
var myPeriodicSound:声音;
var myPeriodicSoundLocation:字符串=”http://periodic_sound_location";
声音:声音;
var myocasionalsoundlocation:字符串=”http://occasional_sound_location";
//用于迭代初始化例程
var mySoundArray:Array=[myAmbientSound,myPeriodicSound,myocasionalSound];
var mySoundLocation:Array=[myAmbientSoundLocation,myPeriodicSoundLocation,MyocasionSoundLocation];
//遍历数组并初始化
for(变量i:int=0;i

此时,我认为
mySoundArray[0]
将引用与
myAmbientSound
相同的对象;但是,访问
myAmbientSound
会引发空指针异常,而
mySoundArray[0]
会按预期工作并引用
Sound
对象。我在这里误解了什么?

定义变量并不是创建指针

// This line is only creating a QName, but no pointer.
// Value of "myAmbientSound" is "null".
var myAmbientSound : Sound;

// Here, you put the reference pointed by myAmbientSound into the array.
// It is null, so mySoundArray[0] will also be null.
var mySoundArray : Array = [myAmbientSound];

// Here, you assign a new pointer to the index 0 of mySoundArray.
// It is simply overwriting the "null" value, but there is no
// connection to myAmbientSound.
mySoundArray[0] = new Sound();

// myAmbientSound is still null, as it is still pointing to nothing.
trace(myAmbientSound);  // null
// But index 0 of mySoundArray holds a pointer to the sound you instanciated.
trace(mySoundArray[0]); // [Object Sound]
要实现您所追求的目标,您必须做到以下几点:

// Creating the variable and pointing it to an object instance.
var myAmbientSound : Sound = new Sound();

// Here, the pointer isn't null, so the reference can be added to the array.
var mySoundArray : Array = [myAmbientSound];

// And now, both accessors points to the same object instance.
trace(myAmbientSound);  // [Object Sound]
trace(mySoundArray[0]); // [Object Sound]

它更像java引用变量,而不是C指针

var myAmbientSound:Sound;
var myPeriodicSound:Sound;
var myOccasionalSound:Sound;
//these variables are not initialized and hence contain null values
现在创建一个数组,其中包含这些变量的当前值(null)

var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound];
该数组现在包含三个空值
[null,null,null]
,而不是预期包含的指向
声音
对象的三个指针


现在,当您调用
mySoundArray[0]=new Sound()时
将创建一个新的
Sound
对象,并将其地址分配给数组的第一个位置-它不会修改
myAmbientSound
变量。

通常,ActionScript、Java和其他语言中的引用与C/C++中的引用不同。如果引用像在C/C++中一样工作,那么您编写的代码将是正确的,并且可以按预期工作。通常,您应该尝试将引用视为自动取消引用的指针。您的代码是C/C++引用和现代引用之间差异的一个很好的例子

下面是此行为应用于垃圾收集器时的后果示例:

var someRef:Sound = new Sound();
someRef = null;
那么我在第一行中创建的声音对象仍然存在,并且可能继续存在。记住这一点很重要,因为如果在AS3中注册事件侦听器,则会创建对它们的额外引用,从而防止它们被GC破坏。这就是为什么您几乎应该始终使用对AddEventListener的完整调用,强制它使用弱引用(GC不计算弱引用)

此外,请记住,所有函数调用在AS3中都是ByVal。所以这个代码不起作用:

function initSound(a:Sound, b:String):void {
    a = new Sound();
    a.load(new URLRequest(b);
}

var myAmbientSound:Sound;
var myAmbientSoundLocation:String = "http://ambient_sound_location";
initSound(myAmbientSound, myAmbientSoundLocation);

好消息是,大多数具有内置垃圾收集的语言对于引用都有相同的行为,因此一旦掌握了窍门,您就能够更快地掌握这些语言。

因为其他语言已经花时间提出了一些非常好的解释,相反,我将尝试直截了当地回答您提出的问题:

此时,我认为
mySoundArray[0]
将引用与
myAmbientSound
相同的对象

但是
myAmbiendSound
没有引用任何内容。从您的代码:

var myAmbientSound:Sound;
上面只是创建了一个类型为Sound的局部变量,一个潜在的引用。用外行的话来说,可以指向某物的“手指”。所有局部变量都是引用。顺便说一下,并不是所有的引用都是局部变量,对象属性也是引用,
Array
Vector
元素也是。无论如何,上面的表达式不会创建
Sound
类的对象。它只声明一个局部变量,可以引用
Sound
类的对象。声明时,它有一个特殊值
未定义

像上面那样声明一个变量和给它赋值是有区别的。运算符
new
创建一个对象并返回对该对象的引用。赋值运算符,
=
,得出左侧的参考值,右侧的参考值,粗略地说

使局部变量位于对象上方的一种方法是:

myAmbientSound = new Sound();
但是,在您的例子中,正如我所说,
myAmbientSound
变量有一个特殊的
未定义的值,因为您只是声明了它,还没有给它赋值。此外,正如我们从代码中看到的,它在代码片段的整个运行时中没有引用任何内容

现在,在我解释你最终在数组中放入的行之前:

 var mySoundArray:Array = [ myAmbientSound, ...
,您必须记住数组元素与对象属性非常相似,也是引用-例如,
mySoundArray[0]
可以引用对象,也可以
mySoundArray[1]
等等

上面的代码行声明了一个新的局部变量,并使其引用一个新的数组对象。一条语句中的声明和定义

现在,由于我们已经确定局部变量
myAmbiendSound
包含特殊的
未定义的
值,因此第一个数组元素最终引用了相同的值-
未定义的
最初。在稍后的循环中,第一个元素(或者,如果我们要拘谨的话,在变量
i
引用的编号处的元素)引用了一个新的
声音
对象。在这一点上(就像我们观察到的那样,在代码片段的整个范围内),由于
myAmbiendSound
未定义的
,比较两者是否相等将失败——它们不引用相同的对象,它们引用的对象也不被视为“相等”(h)