Js中如何克隆对象?

更新日期: 2021-05-03阅读: 926标签: 对象

当我们想要复制原始值和引用值(对象)时,它们的行为会大不相同。


原始值

我们假设一个变量 name 具有一个与之关联的原始值(number,string,boolean,undefined 和null)。 如果我们将此变量 name 复制到另一个变量name2 ,则原始变量的任何修改都不会影响到第二个变量,因为它们是原始值。

let name="fly63";
let name2= name;
console.log (name, name2); // fly63, fly63
name="前端";
console.log (name,name2); // 前端 fly63


引用值

但是,如果我们对引用类型的值进行相同的操作,则我们对一个变量所做的任何更改也将反映在另一个变量中,因为两个变量都指向同一对象。


数组

要拷贝数组,slice()方法用于创建数组的新副本。 可以独立修改此副本,而不会影响原始数组。

如果未传递任何参数,则它会精确复制数组,但数字也可以作为参数传递。 如果仅传递一个数字,它将确定我们要从其进行复制的索引的值,而如果传递两个数字,则将标记开始和结束。

// 示例1
const names = ['fly63', '前端', 'java'];
const names2 = names;
console.log(names, names2);
// ["fly63", "前端", "java"] 
// ["fly63", "前端", "java"] 

// 示例2
names2[2] = 'web';
console.log(names, names2);
//  ["fly63", "前端", "web"] 
//  ["fly63", "前端", "web"] 

// 示例3
const name2 = names.slice();
names[2] = '前端教程';
console.log(name2, names2)
// ["fly63", "前端", "web"]
//  ["fly63", "前端", "前端教程"]

对象

当引用值是一个对象时,也会发生同样的情况,对其属性之一的任何修改都会影响这两个变量。 若要克隆对象,请使用 Object.assign() 方法,该方法会将一个或多个源对象的所有可枚举属性的值复制到目标对象,但是此方法仅对对象的一个浅拷贝。

// 示例1
const names = {
  name: 'fly63',
  surname: 'web前端网'
}

const names2 = names;
console.log(names, names2) // 打印结果是一模一样的

// 示例2
names2.surname ='web前端';
console.log(names, names2)

// {name: "fly63", surname: "web前端"}
// {name: "fly63", surname: "web前端"}

// 示例3
const names3 = Object.assign({}, names);
names3.surname = 'web前端网';
console.log(names, names3)

// {name: "fly63", surname: "web前端"}
// {name: "fly63", surname: "web前端网"}

要对对象进行深拷贝,需要使用其他方法。

正如我们所说,Object.assign()方法只是一个浅拷贝(即,当我们的对象没有其他对象作为属性时)才有效。 在这些情况下,必须对对象进行深拷贝。

与浅拷贝不同,深拷贝以递归方式复制每个子对象,直到所有涉及的对象都被复制为止。

我们可以使用什么方法复制对象的深层副本?

JSON.parse(JSON.stringify(obj))

此方法使用JSON.stringify()将对象转换为字符串,然后再用JSON.parse()将其转换回对象。 此方法对简单对象有效,但如果对象属性是函数时无效。

const names = {
  name: 'fly63',
  surname: 'web前端网',
  social: {
    wx: '大迁世界',
    url: 'www.lsp.com'
  }
}
const names2 = JSON.parse(JSON.stringify(names));
names2.social.url = 'www.baidu.com';
console.log(names, names2);

/** 
{
  name: "fly63"
  social: {wx: "大迁世界", url: "www.lsp.com"}
  surname: "web前端网"
}
*/

/** 
{
  name: "fly63"
  social: {wx: "大迁世界", url: "www.baidu.com"}
  surname: "web前端网"
}
*/


深度拷贝

另一种非常有趣和优雅的对象深度复制方法是使用递归函数。

我们创建了一个deepClone(object)函数,将想要克隆的对象作为参数传递给它。在函数内部,将创建一个局部变量克隆,这是一个空对象,其中将从起始对象克隆的每个属性都将添加到该对象中。

具体思路:

  • 如果该属性不是对象,则将其简单地克隆并添加到新的克隆对象中。
  • 如果属性是对象,则再次执行deepClone(value)函数,并将属性的值(在这种情况下为对象)作为参数传递,并重复相同的过程。
function deepClone(object) {
  var clone = {};
  for (var key in object) {
    var value = object[key];
    if (typeof(value) !== 'object') {
      clone[key] = value;
    } else {
      clone[key]=deepClone(value);
    }
  }
  return clone;
} 

deepClone({value1:1,value2:{value3:2}});
//{value1:1,value2:{value3:2}}
deepClone({value1:1,value2:{value3:{value3b:3}}});
//{value1:1,value2:{value3:{value3b:3}}}

原文:https://www.ma-o.org/en/


链接: https://www.fly63.com/article/detial/10373

JavaScript中创建对象的7种模式

ECMA-262把对象定义为:”无需属性的集合,其属性可以包含基本值、对象或者函数。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正因为这样,我们可以把ECMAScript的对象想象成散列表:无非就是一组名对值,其中值可以是数据或函数。

JavaScript数组、对象合并的多种方法实现

这篇文章讲解Js数组和对象的一些使用技巧,如何将不同的数组,对象合并/结合为1个的方法

Js通过.或者[]访问对象属性的语法、性能等区别

在JavaScript中可以使用 . 或者 [ ] 来访问对象的属性,但是对象中方法只能通过 . 来获取;使用.运算符来存取对象的属性的值。或者使用[]作为一个关联数组来存取对象的属性。但是这两种方式有什么区别了?

js中关于for...in遍历对象属性的顺序问题

对象使用obj.length时,它得到的值是undefined的,所以只能通过for...in循环获取对象的属性,我们发现并没有按属性的顺序显示,而且顺序在各个浏览器下显示也不同。 这是为什么呢?

JS声明对象时属性名加引号与不加引号的问题

JS声明对象时属性名加引号与不加引号的问题,一般情况下属性名加引号和不加引号是都可以的,效果是一样的。如果属性名是数字,则必须用“”包围,并且用 [] 方括号访问。

javascript的本地对象,内置对象和宿主对象

javascript的原生对象:也叫内部对象、本地对象、native object;内置对象:Global(全局对象)、Math ;宿主对象:有宿主提供的对象,在浏览器中window对象以及其下边所有的子对象(如bom、dom等等),在node中是globla及其子对象,也包含自定义的类对象。

JavaScript 判断对象中是否有某属性

判断对象中是否有某属性的常见方式总结,不同的场景要使用不同的方式。一点( . )或者方括号( [ ] )、二in 运算符、三hasOwnProperty()。三种方式各有优缺点,不同的场景使用不同的方式,有时还需要结合使用

JavaScript Error对象详解

error,指程序中的非正常运行状态,在其他编程语言中称为“异常”或“错误”。解释器会为每个错误情形创建并抛出一个Error对象,其中包含错误的描述信息。

如何禁止JavaScript对象重写?

由于JavaScript的灵活性,我们可以轻易地重写(override)一些于其他人定义的对象(object)。换句话说,任何人都可以重写我们所定义的对象。这是一个非常强大的特性,许多开发者都有兴趣试试,来拓展或者修改某些对象的行为。

JavaScript面向对象编程中_优雅的类写法

虽然现在已经是ES6的时代,但是,还是有必要了解下ES5是怎么写一个类的。本文详述JavaScript面向对象编程中的类写法,并分步骤讲述如何写出优雅的类。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!