ES6 React-引用,浅表副本和深表副本之间有什么区别,以及如何比较它们? [英] ES6 React - What are the difference between reference, shallow copy and deep copy and how to compare them?
问题描述
我知道这个问题已经讨论了很多次了,我想我有了一个基本的想法.我从StackOverflow找到了一些评价最高的答案:
I know this question has been discussed so many times, and I think I got a basic idea. There are some top rated answers I found from StackOverflow:
- What is the difference between a deep copy and a shallow copy?
- Deep Copy and Shallow Copy
但是所有答案对我来说似乎都很模糊.
让我们考虑下面的示例:
But all the answers seems very fuzzy to me.
Let's consider the example below:
const user = {
name: "James",
age: 33,
highlights: {
career: "Basketball player",
NBAChampion: [2012, 2013, 2016],
},
promotion: () => ("Get LeBron15 now!"),
};
const james = user;
const clone = { ...user };
const clone2 = Object.assign({}, user);
const clone3 = JSON.parse(JSON.stringify(user));
const clone4 = {
...user,
highlights: {
...user.highlights,
// I comment the it out, so now NBAChampion is a reference rather than copy!
// NBAChampion: [...user.highlights.NBAChampion]
}
};
user.age++;
user.highlights.career = "football player";
console.log('james', james, james === user, james == user);
console.log('clone', clone, clone === user, clone == user);
console.log('clone2', clone2, clone2 === user, clone2 == user);
console.log('clone3', clone3, clone3 === user, clone3 == user);
// console.log(clone3.promotion()); // My problem with clone3 is that function's been removed.
console.log('clone4', clone4, clone4 === user, clone4 == user);
-
james
是参考,它始终与用户完全相同; -
clone
是副本. 是浅拷贝还是深拷贝?name
和age
与user
是分开的,但是highlights
仍然是参考. -
clone2
的行为与clone
完全相同. -
clone3
是从字符串转换而来的. 这是一个深层副本吗?这不是一个完美的克隆,因为函数(如果有任何)不会保存以这种方式进行转换. -
clone4
被复制到user
的每一层,所以我可以称其为深度复制".
但是,如果 spread运算符仅在有时创建深拷贝,那么我如何测试新对象是否是深拷贝?
james
is a reference, it's always exactly same as user;clone
is a copy. Is it a shallow copy or deep copy? Thename
andage
are separated fromuser
, but thehighlights
is still a reference.clone2
behaves exactly the same asclone
.clone3
is converted from a string. Is it a deep copy? It is not a perfect clone, since functions (if there's any) are not save to convert this way.clone4
is copied every layer ofuser
, so I can call it a "deep copy".
However if the spread operator only creates deep copy sometimes, then how can I test if the new object is a deep copy or not?
更新:我在clone4
中将NBAChampion
注释掉了,所以现在NBAChampion是参考,而不是副本!如果我在user.highlights.NBAChampion
中推送新值,则clone4
也会更新.
我们应该怎么称这种类型的对象?它既不是浅表副本也不是深表副本.
Update: I commented NBAChampion
out in clone4
, so now NBAChampion is a reference rather than copy! If I push a new value in user.highlights.NBAChampion
, clone4
will also updates.
What should we call this type of object? It's neither a shallow nor deep copy.
反应具有shouldComponentUpdate()
功能,用于比较浅表副本.有链接.
在React中源代码行:356),浅比较是这样完成的:
React has a shouldComponentUpdate()
function which compares shallow copy. There is the link.
In React source code (Line: 356), the shallow comparison is done like this:
shouldComponentUpdate(nextProps) {
return this.props.children !== nextProps.children;
}
在上面的代码演示中,console.log
中的第二个和第三个参数显示了clone
和user
之间的比较结果.但是,只有第一个副本返回true
. (注意:严格比较和抽象比较之间没有区别)
In the code demo above, the 2nd and 3rd parameters in console.log
show the comparison results between clone
and user
. However, only 1st copy returns true
. (Note: there is no different between strict comparison and abstract comparison)
如果我将shouldComponentUpdate
应用于上面的演示,显然只有james
和user
会返回true
.因此james
是Facebook代码中的浅表副本.然后我的问题是:
If I apply shouldComponentUpdate
to the demo above, obviously only james
and user
will return true
. So james
is a shallow copy in Facebook's code. Then my questions are:
- 引用和浅表副本在JS中是否完全相同?如果没有,为什么要这么做?
- 如何在测试案例中测试对象是浅表副本还是深表副本?
- Are reference and shallow copy exactly the same thing in JS? If not, why React do this?
- How can I test a object is a shallow copy or deep copy in my test case?
这个问题花了我很多时间来做.欢迎提供任何带有示例的清晰说明.
非常感谢.
The question took me lots of time to craft. Any clear explanation with example is welcome.
Thanks a lot.
推荐答案
让我们考虑下面的示例
Let's consider the example below
clone
和clone2
较浅,仅影响原始对象的属性. clone3
和clone4
很深.
clone
and clone2
are shallow, only properties of original object are affected. clone3
and clone4
are deep.
但是,如果散布运算符有时仅创建深层副本,那么如何测试新对象是否为深层副本?
However if the spread operator only creates deep copy sometimes, then how can I test if the new object is a deep copy or not?
在clone4
的情况下,它会创建深层副本-只要深度由开发人员控制即可.通常,无需在React中测试对象是否是深层复制或只是不同,因为这种检查非常昂贵,并且需要遍历两个比较对象中的嵌套对象,并逐个属性地对其进行比较.
It creates deep copy in case of clone4
- as long as the depth is controlled by a developer. Generally there's no need to test if an object is deep copy or just different in React, because this check is expensive and requires to traverse nested objects in both compared objects and compare them property by property.
性能是React依赖不变性的原因.如果新值不等于===
,则将其视为其他值.
Performance is the reason why React relies on immutability. If a new value isn't ===
equal, it's considered a different value.
所以詹姆斯是Facebook代码中的浅表副本.
So james is a shallow copy in Facebook's code.
不是.这是分配给另一个变量的引用.它仍然是同一个对象.
It isn't. It's a reference that was assigned to another variable. It's still same object.
引用和浅表副本在JS中是否完全相同?
Are reference and shallow copy exactly the same thing in JS?
参考不是副本.因此它也不是浅表副本.
A reference isn't a copy. So it isn't shallow copy, too.
我在clone4中将NBAChampion注释掉了,所以现在NBAChampion只是一个参考,而不是复制品!如果我在user.highlights.NBAChampion中推送新值,则clone4也将更新. 我们应该怎么称这种类型的对象?它既不是浅拷贝也不是深拷贝.
I commented NBAChampion out in clone4, so now NBAChampion is a reference rather than copy! If I push a new value in user.highlights.NBAChampion, clone4 will also updates. What should we call this type of object? It's neither a shallow nor deep copy.
这只是一个副本.它没有特定的名称,因为很少需要进行此类选择性复制.如果要使它像深复制一样工作,则应将其称为错误.
It's just a copy. It doesn't have specific name, because there's rarely a need to do such selective copies. If the intention is to make it act like deep copy, it should be called a mistake.
这篇关于ES6 React-引用,浅表副本和深表副本之间有什么区别,以及如何比较它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!