Why do arrays do this?

If I create an array and populate it with points, then change one of the points, it doesn’t change in the array. Like this:

var pt1:Point = new Point(1, 1);
var pt2:Point = new Point(2, 2);

var arr:Array = [pt1, pt2];
trace(arr);                            // (x=1,y=1),(x=2,y=2)
pt1 = new Point(4, 4);
trace(arr);                            // (x=1,y=1),(x=2,y=2)

I can “update” the array using splice,…

arr.splice(0, 1, pt1);
trace(arr);                            // (x=4,y=4),(x=2,y=2)

Why doesn’t the change reflect immediately in the array? And is there a better way to do that “update” than that?

Arrays don’t reference their contents by variable name, they do it by value. So when you say

var arr:Array = [pt1, pt2];

You’re saying “put what pt1 points to and what pt2 points to into the array and immediately forget any association those values have with those variables.”

Then, when you say

pt1 = new Point(4, 4);

You’re creating a brand new, 3rd Point value and changing the variable pt1 that was pointing to Point(1,1) to now, instead, point to the Point(4,4). Point(1,1) still exists. You’re not changing it. The only thing you changed is what the variable pt1 references.

When you made the array, the array captured the values that the variables pt1 and pt2 referenced at that time then disassociated itself from those variables. It captured the values and created new references to point to them in the form of arr[0] and arr[1]. And in using splice you can change those variables to point to other objects, such as your new 3rd point, now being referenced by pt1 (though instead of splice you can more easily just do arr[0] = pt1).

Do you want an array to reference variables by name and not internally reference the values? Then you’d have to do something tricky like this:

var pt1:Point = new Point(1, 1);
var pt2:Point = new Point(2, 2);

// define the array to contain the variables for the values
// and the object those variables are defined (context)
var arr:Array = [{context: this, key: "pt1"}, {context: this, key: "pt2"}];

// create a custom function to dynamically capture
// the value within the array index from the context
// object and the respective variable name (key)
arr.at = function(index:int):Object {
    var data = this[index];
    return data.context[data. key];
};
trace(arr.at(0)); // (x=1,y=1)
pt1 = new Point(4, 4);
trace(arr.at(0)); // (x=4,y=4)

So instead of capturing the values of whats in pt1 and pt2, those variables are being referenced by name so they can be looked up on demand and get whatever value it is they point to when asked for.

Edit: If you want to do it the first way (recommended) then you edit the Point rather than redefining it. Since both the array and the pt1 variable reference the same Point object, changes to that object through any reference (var or array) will be reflected in both since, well they’re the same.

My something trick was going to be the AS3 equivalent of this:

let p1 = new Point(4, 5)
let p2 = new Point(10, 20)

let arr = new Proxy([_ => p1, _ => p2], { get: (t, i) => t[i]() })

p1 = new Point(44, 55)

console.log(arr[0]) // magic

You’re funny :laughing:

Whaddaya mean? Like, it would just take a lot longer to write out an AS3 Proxy subclass, and write out function(){} a few times instead of those fat arrows.