为了账号安全,请及时绑定邮箱和手机立即绑定

当我执行“x=y”并更改“x”后,它也会更改“y”。我该如何防止这种情况?

当我执行“x=y”并更改“x”后,它也会更改“y”。我该如何防止这种情况?

吃鸡游戏 2023-09-21 17:09:28
例如我有listings数组:[ { name: 'bob', price: '10' }, { name: 'jack', price: '12' } ]我正在尝试找到最低卖家并稍后使用它的数据。我愿意var currentLowestSeller = listings[0];现在currentLowestSeller是:{ name: 'bob', price: '10' }后来我做了更改,currentLowestSeller但我不想listings更改主数组。我currentLowestSeller.price = currentLowestSeller.price * 0.5;这样做了,这个列表数组看起来像这样:[ { name: 'bob', price: 5 }, { name: 'jack', price: '12' } ]我该如何防止这种情况?如果你想重新创建它,只需运行以下代码:var listings = [];var name1 = 'bob';var name2 = 'jack';var price1 = '10';var price2 = '12';listings.push({  name: name1,  price: price1})listings.push({  name: name2,  price: price2})var currentLowestSeller = listings[0];currentLowestSeller.price = currentLowestSeller.price * 0.5;console.log(listings);我尝试过的:我尝试在执行任何操作之前创建数组的副本listings。var unchangedListings = listings;var currentLowestSeller = listings[0];currentLowestSeller.price = currentLowestSeller.price * 0.5;console.log(unchangedListings);但这没有用。后来我决定这const unchangedListings = listings;会有所帮助。但由于某种原因,它也会更改定义为常量的值。
查看完整描述

4 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

var unchangedListings = listings;

这意味着,unchangedListings正在指示 的值listings,因此如果您更改该unchangedListings值,则意味着您也在更新listings

为了防止这种情况,您需要克隆该值。您应该深度克隆该对象。

var currentLowestSeller = JSON.parse(JSON.stringify(listings[0]))

或者

var currentLowestSeller = Object.assign({}, listings[0])


查看完整回答
反对 回复 2023-09-21
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

问题的根源

您看到的行为对于大多数语言来说都是常见的,与 javascript 无关。


数组仅包含对其所包含对象的引用。从数组(或与此相关的对象)中提取键不会复制该键的值。如果是这种情况,就无法对程序的状态进行任何更改。


var a = { toto: 1 };  // create object

var b = a;            // b is pointing the the same object

b['toto'] = 2;        // update the object (there is only one)


console.log(a == b);  // true because a and b are the SAME object (not just equal,

                      // both a and b point to the same place in the computer memory)


console.log(a);       // { toto: 2 } both objects have been edited

如果需要操作一个对象而不修改原始对象,则需要显式地创建一个副本。


但是,当使用嵌套对象或嵌套数组时会出现问题。您需要“深拷贝”还是“浅拷贝”?


浅拷贝

浅复制意味着仅复制“第一层”。


var a = { toto: 1, tata: { tutu: 1 } };

var b = { ... a }; // make a "shallow copy"


// We change "b", did "a" change? => No

b.toto = 2;

console.log(a); // { toto: 1, tata: { tutu: 1 } }

                // "a" was not modified!


console.log(b); // { toto: 2, tata: { tutu: 1 } }

                // "b" was modified!


// we change a nested object in "b", did "a" change? => Yes

b.tata.tutu = 2;

console.log(a); // { toto: 1, tata: { tutu: 2 } }

                // "a" was modified!


console.log(b); // { toto: 2, tata: { tutu: 2 } }

                // "b" was modified!

深拷贝

深层复制将复制所有嵌套数组和对象(并且会带来显着的性能成本)。


Javascript 没有内置执行深拷贝的语言,因为它不是常见的操作,而且成本高昂。


执行对象深层复制的最常见方法是使用 JSON 内置函数,但许多方法存在不同的优缺点(例如,使用 JSON 内置函数速度很快,但如果对象包含 或 实例,则会中断NaN)Date。


var a = { toto: 1, tata: { tutu: 1 } };

var b = JSON.parse(JSON.stringify(a)); // make a "deep copy"


// a and b are now completely different, they share nothing in memory

// we can edit any subobject, they will not be any consequence between them.

a.tata.tutu = 2;


查看完整回答
反对 回复 2023-09-21
?
莫回无

TA贡献1865条经验 获得超7个赞

如果列表或字典是嵌套的,您可以使用Ramda 库clone中的内容:


import { clone } from 'ramda';


var currentLowestSeller = clone(listings[0]);



查看完整回答
反对 回复 2023-09-21
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

Javascript(以及许多其他语言)最重要的概念之一是引用类型的概念。Javascript 有 3 种通过引用传递的数据类型:ArrayFunctionObject

在你的情况下:

var unchangedListings = listings; // still points to listings
var currentLowestSeller = listings[0]; // changes listings

在改变数组之前复制数组始终是一个好习惯:

const currentLowestSeller = [... listings]; // currentLowestSeller points to a new array


查看完整回答
反对 回复 2023-09-21
  • 4 回答
  • 0 关注
  • 106 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信