在JavaScript中的类中,push和concat的工作方式有何不同

How do push and concat work differently in classes in JavaScript

本文关键字:工作 方式 concat 何不同 push JavaScript      更新时间:2023-09-26

由于某种原因,当我的类定义中有一个数组,然后我使用push()函数附加到我的数组时,数组变量似乎会为我创建的该类的所有未来对象更新。

这是我正在使用的代码:

var CircleSprite = cc.Class.extend({
circles:[],
thing: "",
ctor:function(target, n, x, y) {
    this.num = n;

    //This should always print 0 whenever a new object is created, but it's storing the object from the previous creation as well
    cc.log("num circles: " + this.circles.length); 
    for(var i=0; i<n; i++)
    {
        var circleSprite = new cc.Sprite.create(res.circle);
        circleSprite.setPosition(cc.p(x, y+circleSprite.height*this.circles.length));

        this.circles.push(circleSprite); //doesn't work like I want
        //this.circles = this.circles.concat(circleSprite); works well
    }
    //This code works as expected for each object
    cc.log("this thing: " + this.thing); //prints ""
    this.thing = "hi"+n;
    cc.log("this thing: " + this.thing); //print "hi2", "hi3", etc.
},

然而,当我使用concat()函数进行追加时,数组会按预期工作,并且只为每个对象更新。

那么,为什么push()会修改所有实例的变量呢?

因为所有实例都引用同一个变量。push附加到现有数组,而concat则使用组合值创建一个副本。

这是一个问题,因为类的每个实例都持有对同一数组的引用。它们每个都有一个不同的变量,因此您可以复制并替换该引用,但最初它们都引用了完全相同的数组。JS中的对象是可变的,因此您可以修改数组并影响类的每个实例。字符串不是,所以任何附加或赋值都会创建一个副本,并且只有一个实例会引用该副本,所以您不会看到这个问题。

因为您已经在类定义中声明了数组,所以它相当于Java或C++中的静态字段。类的所有实例都将共享相同的值。

要解决此问题,您应该在构造函数(this.circles = [])中声明变量,在那里它将为每个实例初始化,并仅分配给该特定实例。

除了其他不错的答案外,我想添加以下来自Microsoft文档的两种方法的描述,并提供参考链接:

concat()方法返回一个新数组,该数组由调用它的数组与作为参数提供的数组和/或值组成
push()方法将一个或多个元素添加到数组的末尾,并返回数组的新长度。

参考:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push