如何在同一列表中多次推入变量并保留其值?

3

我遇到了一个问题:我有一个函数,在这个函数中有一个变量,每次调用该函数时它的值都在改变。在函数的代码后面,我把这个变量推入一个列表中。但是当我多次执行这个操作时,变量都被正确地存储,但是所有的值都与最新的值相同。

var new_plane; //I define these variables here because I want to use it again in other functions
var list_plane = [];

var Planes = { //I define the object
    number: "",
    airline: ""
};

function add_plane() {
    new_plane = Planes;
    new_plane.number = 10; //Random number
    new_plane.airline = "Air France"; //Random airline of a list

    list_plane.push(new_plane); //I push the variable in the list

    for (let i = 0; i < list_plane.length; i++) {
        document.body.innerHTML += list_plane[i].number + " " + list_plane[i].airline + "<br />"; //The body is used for the example and the output too
    };
};

当输入第一个平面时,一切都很好。但是设置第二个平面时,两个平面具有相同的值,而不是预期的自己的值。

5个回答

2
最初的回答
移动
var Planes = { //I define the object
    number: "",
    airline: ""
};

在函数内部进行操作,否则数组中的每个元素都将引用相同的对象。


另一种解决方法是使用Plane模式作为新对象的模板。

// global
var Planes = {
        number: "",
        airline: ""
    };

function add_plane() {
    var new_plane = Object.assign({}, Planes); // get copy

    new_plane.number = 10;
    new_plane.airline = "Air France";

    list_plane.push(new_plane);

    for (let i = 0; i < list_plane.length; i++) {
        document.body.innerHTML += list_plane[i].number + " " + list_plane[i].airline + "<br />";
    } // no semicolon here
} // no semicolon here

将Planes的声明更改为面向对象编程将更为常见。 - computercarguy
@computercarguy,没错,如果这个概念被采纳了,但其他概念也同样适用。 - Nina Scholz

1
这是因为new_plane指向同一个对象,你将其多次推入数组中。
你可能想每次都初始化一个新的对象,像这样:
function add_plane() {
  const new_plane = {
    number: 10,
    airline: "Air France"
  };

  list_plane.push(new_plane);

  //...
}

然而我建议将数组作为参数传递给add_plane函数,甚至更好的方法是使用面向对象编程。


1
无论您对该对象有多少引用(即使在同一数组中),总体上仍然只有一个对象。而您正在更新该对象的属性。
相反,定义一个新对象插入到数组中:
function add_plane() {
    let new_plane = {
        number: 10, //Random number
        airline: "Air France" //Random airline of a list
    };

    list_plane.push(new_plane); //I push the variable in the list

    for (let i = 0; i < list_plane.length; i++) {
        document.body.innerHTML += list_plane[i].number + " " + list_plane[i].airline + "<br />"; //The body is used for the example and the output too
    };
};

0

这是因为你需要创建一个新的 Planes 实例:new_plane = new Planes();

你目前只声明了一个单一对象 Planes,并且你不断更新该实例的值。无论你是否将其添加到 list_plane 中,该对象的任何其他用途都将被更新。

编辑: 你还需要更改你的声明为:

function Planes () { //I define the object
    number = "";
    airline = "";
}

这就是如何使您的代码面向对象。我之前错过了这个区别,对此感到抱歉。


不行,因为它告诉我飞机不能用作这种类型的对象。 - Alex

0
var list_plane = [];

var Planes = function (n, a) { //I define the object
    this.number = n;
    this.airline = a;
};

function add_plane(num, air) {
    list_plane.push(new Planes(num, air)); //I push the variable in the list
}

function printAirplanes () {
    for (let i = 0; i < list_plane.length; i++) {
        document.body.innerHTML += list_plane[i].number + " " + list_plane[i].airline + "<br />"; //The body is used for the example and the output too
    };
};

add_plane(10, "Air france");
add_plane(15, "KLM");

printAirplanes();

从开发角度来看,我认为这更加简洁。有一件重要的事情:我认为你应该将添加方法中的for循环移除。

这也可以重写为ES2015和其他版本,但我想这可以留作另一个时间的作业。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接