vue对象深拷贝_JavaScript 中对象的深拷贝

对象的深拷贝与浅拷贝的区别如下:

浅拷贝:仅仅复制对象的引用,而不是对象本身;

深拷贝:把复制的对象所引用的全部对象都复制一遍。

一. 浅拷贝的实现

浅拷贝的实现方法比较简单,只要使用是简单的复制语句即可。

1.1 方法一:简单的复制语句 /* ================ 浅拷贝 ================ */

function simpleClone(initalObj) {

var obj = {};

for ( var i in initalObj) {

obj[i] = initalObj[i];

}

return obj;

}

客户端调用 /* ================ 客户端调用 ================ */

var obj = {

a: "hello",

b: {

a: "world",

b: 21

},

c: ["Bob", "Tom", "Jenny"],

d: function() {

alert("hello world");

}

}

var cloneObj = simpleClone(obj); // 对象拷贝

console.log(cloneObj.b); // {a: "world", b: 21}

console.log(cloneObj.c); // ["Bob", "Tom", "Jenny"]

console.log(cloneObj.d); // function() { alert("hello world"); }

// 修改拷贝后的对象

cloneObj.b.a = "changed";

cloneObj.c = [1, 2, 3];

cloneObj.d = function() { alert("changed"); };

console.log(obj.b); // {a: "changed", b: 21} // // 原对象所引用的对象被修改了

console.log(obj.c); // ["Bob", "Tom", "Jenny"] // 原对象所引用的对象未被修改

console.log(obj.d); // function() { alert("hello world"); } // 原对象所引用的函数未被修改

1.2 方法二:Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。 var obj = { a: {a: "hello", b: 21} };

var initalObj = Object.assign({}, obj);

initalObj.a.a = "changed";

console.log(obj.a.a); // "changed"

二. 深拷贝的实现

要实现深拷贝有很多办法,有最简单的 json.parse() 方法,也有常用的递归拷贝方法,和ES5中的 Object.create() 方法。

2.1 方法一:使用 JSON.parse() 方法

要实现深拷贝有很多办法,比如最简单的办法是使用 JSON.parse(): /* ================ 深拷贝 ================ */

function deepClone(initalObj) {

var obj = {};

try {

obj = JSON.parse(JSON.stringify(initalObj));

}

return obj;

} /* ================ 客户端调用 ================ */

var obj = {

a: {

a: "world",

b: 21

}

}

var cloneObj = deepClone(obj);

cloneObj.a.a = "changed";

console.log(obj.a.a); // "world"

这种方法简单易用。

但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

2.2 方法二:递归拷贝

代码如下: /* ================ 深拷贝 ================ */

function deepClone(initalObj, finalObj) {

var obj = finalObj || {};

for (var i in initalObj) {

if (typeof initalObj[i] === 'object') {

obj[i] = (initalObj[i].constructor === Array) ? [] : {};

arguments.callee(initalObj[i], obj[i]);

} else {

obj[i] = initalObj[i];

}

}

return obj;

}

上述代码确实可以实现深拷贝。但是当遇到两个互相引用的对象,会出现死循环的情况。

为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。

改进版代码如下: /* ================ 深拷贝 ================ */

function deepClone(initalObj, finalObj) {

var obj = finalObj || {};

for (var i in initalObj) {

var prop = initalObj[i];

// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况

if(prop === obj) {

continue;

}

if (typeof prop === 'object') {

obj[i] = (prop.constructor === Array) ? [] : {};

arguments.callee(prop, obj[i]);

} else {

obj[i] = prop;

}

}

return obj;

}

2.3 方法三:使用Object.create()方法

直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。 /* ================ 深拷贝 ================ */

function deepClone(initalObj, finalObj) {

var obj = finalObj || {};

for (var i in initalObj) {

var prop = initalObj[i];

// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况

if(prop === obj) {

continue;

}

if (typeof prop === 'object') {

obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);

} else {

obj[i] = prop;

}

}

return obj;

}

三. 参考:jquery.extend()方法的实现

jQuery.js的jQuery.extend()也实现了对象的深拷贝。下面将官方代码贴出来,以供参考。

官方链接地址:https://github.com/jquery/jquery/blob/master/src/core.js。 jQuery.extend = jQuery.fn.extend = function() {

var options, name, src, copy, copyIsArray, clone,

target = arguments[ 0 ] || {},

i = 1,

length = arguments.length,

deep = false;

// Handle a deep copy situation

if ( typeof target === "boolean" ) {

deep = target;

// Skip the boolean and the target

target = arguments[ i ] || {};

i++;

}

// Handle case when target is a string or something (possible in deep copy)

if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {

target = {};

}

// Extend jQuery itself if only one argument is passed

if ( i === length ) {

target = this;

i--;

}

for ( ; i < length; i++ ) {

// Only deal with non-null/undefined values

if ( ( options = arguments[ i ] ) != null ) {

// Extend the base object

for ( name in options ) {

src = target[ name ];

copy = options[ name ];

// Prevent never-ending loop

if ( target === copy ) {

continue;

}

// Recurse if we're merging plain objects or arrays

if ( deep && copy && ( jQuery.isPlainObject( copy ) ||

( copyIsArray = jQuery.isArray( copy ) ) ) ) {

if ( copyIsArray ) {

copyIsArray = false;

clone = src && jQuery.isArray( src ) ? src : [];

} else {

clone = src && jQuery.isPlainObject( src ) ? src : {};

}

// Never move original objects, clone them

target[ name ] = jQuery.extend( deep, clone, copy );

// Don't bring in undefined values

} else if ( copy !== undefined ) {

target[ name ] = copy;

}

}

}

}

// Return the modified object

return target;

};

这篇文章主要是介绍js关于深拷贝的内容,其它的内容可以查看聚米学院以前发表的文章

### 回答1: 在Vue,我们通常使用深拷贝和浅拷贝来复制Vue对象,这两种方法都有其适用的场景和局限性。 1. 浅拷贝: 浅拷贝是指将对象的引用复制到新变量,新变量只是指向原始对象的内存地址,这意味着如果我们对新对象进行更改,原始对象也会发生更改。 Vue提供了一种浅拷贝对象的方法,可以使用`Object.assign()`或展开运算符`...`,例如: ```javascript let original = { name: 'John', age: 30, address: { city: 'New York', country: 'USA' } } // 使用 Object.assign() 进行浅拷贝 let copy = Object.assign({}, original) // 使用展开运算符 ... 进行浅拷贝 let copy2 = {...original} ``` 在上面的示例,如果我们更改新的对象的“address”属性,原始对象也会发生更改,因为它们指向同一个内存地址。 2. 深拷贝深拷贝是指将对象及其所有嵌套属性的值复制到新变量,而不是只复制原始对象的引用。这意味着对新对象进行更改不会影响原始对象Vue不提供默认的深拷贝方法,但是可以使用第三方库如Lodash的`cloneDeep()`方法或JSON的`parse()`和`stringify()`方法来进行深拷贝。 ```javascript let original = { name: 'John', age: 30, address: { city: 'New York', country: 'USA' } } // 使用 Lodash 的 cloneDeep() 方法进行深拷贝 let copy = _.cloneDeep(original) // 使用 JSON.parse() 和 JSON.stringify() 进行深拷贝 let copy2 = JSON.parse(JSON.stringify(original)) ``` 在上面的示例,如果我们更改新的对象的“address”属性,原始对象不会发生更改,因为它们指向不同的内存地址。 需要注意的是,使用`JSON.parse()`和`JSON.stringify()`进行深拷贝时,有一些情况下无法复制对象的一些特定属性,例如函数、RegExp、Date等,因为它们无法被序列化成字符串。在这种情况下,需要使用其他库或自己编写递归复制对象的代码。 ### 回答2: Vue对象深拷贝和浅拷贝是在处理对象拷贝时涉及到的两种不同的操作方法。 浅拷贝是指在拷贝对象时,只拷贝对象的第一层属性值,当源对象和目标对象的属性值是基本数据类型时,目标对象的属性值会完全独立于源对象,但是当属性值是引用类型时,源对象和目标对象的属性值指向同一个内存地址。 例如,在Vue,我们可以使用浅拷贝来创建一个新的对象,并对其进行修改,而不影响原始对象的值: ```javascript let source = { name: 'Alice', age: 20, skills: ['JavaScript', 'Vue'] }; let copy = Object.assign({}, source); copy.name = 'Bob'; copy.skills.push('React'); console.log(source); // { name: 'Alice', age: 20, skills: ['JavaScript', 'Vue', 'React'] } console.log(copy); // { name: 'Bob', age: 20, skills: ['JavaScript', 'Vue', 'React'] } ``` 从上面的例子可以看出,浅拷贝只是拷贝了对象的第一层属性,当修改拷贝对象的属性时,原始对象的值不会受到影响。但是对象的引用类型属性(如数组)在浅拷贝是共享的,因此对拷贝对象的引用类型属性进行修改,会影响到原始对象的值。 相比之下,深拷贝是指在拷贝对象时,递归地拷贝对象的所有层级属性,即使属性值是引用类型,也会在内存重新创建一个新的引用地址。这样可以实现完全独立的对象拷贝,互不影响。 在Vue,我们可以使用一些库和方法来实现对象深拷贝,如`lodash`库的`cloneDeep`方法或者`JSON.parse(JSON.stringify(obj))`。 然而,需要注意的是对于包含循环引用的对象,使用普通的深拷贝方法可能会导致无限递归,进而导致程序崩溃。因此,在实际开发,对于包含循环引用的对象,需要格外小心处理。 ### 回答3: Vue对象深拷贝与浅拷贝是指对Vue对象进行复制的两种不同方式。 浅拷贝是将原始对象的引用复制一份给新的对象,新对象与原对象共享同一块内存地址。当修改新对象的属性时,原对象的对应属性也会随之改变。这是因为浅拷贝只复制对象的引用,对于引用类型的属性,只是复制了指向同一块内存地址的指针。既然指针指向同一块内存地址,那么无论是新对象还是原对象,当修改该对象的属性时,都会影响到另一个对象深拷贝是创建一个新的对象,并且递归地复制对象的所有属性和子属性。深拷贝会完全复制对象及其引用类型属性所指向的内存地址,即使是嵌套的引用类型属性也会一一复制。当修改新对象的属性时,原对象的对应属性不会受到影响,因为它们指向的是两块独立的内存地址。 在Vue开发,数据的响应式是基于对象的引用关系实现的。当使用浅拷贝进行数据复制时,新对象仍然会指向原对象的引用地址,导致新对象的修改也会影响到原对象,这可能会导致数据更新的不一致性。因此,在需要对Vue对象进行复制时,通常会使用深拷贝来创建一个独立的对象,以保持数据的一致性和独立性。可以使用一些第三方库(如lodash的cloneDeep方法)或者自定义递归方法来实现深拷贝
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值