ES6 React-引用,浅表副本和深表副本之间有什么区别,以及如何比较它们? [英] ES6 React - What are the difference between reference, shallow copy and deep copy and how to compare them?

查看:101
本文介绍了ES6 React-引用,浅表副本和深表副本之间有什么区别,以及如何比较它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经讨论了很多次了,我想我有了一个基本的想法.我从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是副本. 是浅拷贝还是深拷贝? nameageuser是分开的,但是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? The name and age are separated from user, but the highlights is still a reference.
  • clone2 behaves exactly the same as clone.
  • 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 of user, 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中的第二个和第三个参数显示了cloneuser之间的比较结果.但是,只有第一个副本返回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应用于上面的演示,显然只有jamesuser会返回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

cloneclone2较浅,仅影响原始对象的属性. clone3clone4很深.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆