实例化并推送新对象后,将覆盖数组中的每个对象

时间:2018-10-31 12:48:55

标签: javascript

我正在尝试根据用户输入创建对象数组。

该对象被推入数组,但是在下一步,输入将覆盖数组中的每个对象。

我尝试通过category.value,并且效果很好,但是我想通过整个类别。

例如:

  1. 选择A,提交,输出-“ a”(按预期)
  2. 选择B,提交,输出-“ b”,“ b”(预期为“ a”,“ b”)

为什么会这样?

let form = document.getElementById('form');

let category = form.category;

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C(category);

    arr.push(c);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>

2 个答案:

答案 0 :(得分:1)

在代码let类别中的

是对您选择的HTML元素(而不是Javascript对象)的直接引用。此引用被推入数组。每次要求提供值时,您都可以直接从选择的值中获​​取value属性。因此每次都会对其进行更新。

如果您想要一个带有值的Javascript对象,则必须构造一个并将其提供给您的类:

let form = document.getElementById('form');

let category = form.category;

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C({ value: category.value });

    arr.push(c);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>

请注意,它之所以有效是因为Javascript中的字符串是按值传递的,而对象是按引用传递的(实际上是引用的值)。如果您有一个全局类别对象来更新值并将其推送到数组中,则会遇到相同的问题:

let form = document.getElementById('form');

let category = form.category;

let categoryObj = { value: null };

let submit = document.getElementById('formSubmit');

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();
    
    categoryObj.value = category.value;
    let c = new C(categoryObj);

    arr.push(c);
    
    console.log('same problem you had because all items in the array are the same reference to the global object!');
    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i].category.value);
    }
})



class C {
    constructor(category)
    {
        this.category = category;
    }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form id="form">
    <select name="category">
        <option value="-">choose category</option>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
    </select>
    <button id="formSubmit" type="submit">submit</button>

</form>

<script src="test.js"></script>
</body>
</html>

答案 1 :(得分:0)

category对象是整个程序中的同一对象,用户输入只是对其进行更改。当用对象填充数组时,它们实际上是按引用存储的,因此代码中发生的事情是同一对象填充了数组。这就是为什么您遇到描述的重复的原因。

如果相反,您做了例如像这样:

let arr = [];

submit.addEventListener("click",(e)=>{
    e.preventDefault();

    let c = new C(category);

    arr.push(c.category.value);

    for(let i=0;i<arr.length;i++)
    {
        console.log(arr[i]);
    }
});

然后使用实际值填充数组,您将获得期望的结果。如果您想专门存储C实例,可以通过例如在推入数组之前先cloning个对象。