JS的赋值与深浅拷贝实例

JS的赋值与深浅拷贝实例

赋值

  • 基本类型: 传值,在栈内存中的数据发生数据变化的时候,系统会自动为新的变量分配一个新的之值在栈内存中,两个变量相互独立,互不影响的
  • 引用类型: 传址,只改变指针的指向,指向同一个对象,两个变量相互干扰
//基本数据类型赋值
var a = 10;
var b = a;
a++ ;
console.log(a); // 11
console.log(b); // 10

//引用数据类型赋值
let a = { name: '11' }
let b = a
b.name = '22'
console.log(a.name) // 22
console.log(b.name) // 22

浅拷贝

  • 对于基本类型,浅拷贝是对值的复制,拷贝前后对象的基本数据类型互不影响
  • 对于引用类型来说,浅拷贝是对对象地址的复制, 也就是拷贝的结果是两个对象指向同一个地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

注意:浅拷贝只复制一层对象的属性

实现浅拷贝方法

方法一:Object.assign

**语法:Object.assign(target, ...sources) **<br />ES6中拷贝对象的方法,接受的第一个参数target是拷贝后的对象,剩下的参数是要拷贝的对象sources(可以是多个)

例1:

let target = {};
let source = {a:'11',b:{name:'duoduo'}};
Object.assign(target ,source);
console.log(target); // { a: '11', b: { name: 'duoduo' } }

例2:

let target = {};
let source = {a:'11',b:{name:'duoduo'}};

Object.assign(target ,source);

source.a = '22';
source.b.name = 'nana'

console.log(source); // { a: '22', b: { name: 'nana' } }
console.log(target); // { a: '11', b: { name: 'nana' } }

Object.assign注意事项

  1. 只拷贝源对象的自身属性(不拷贝继承属性)
  2. 它不会拷贝对象不可枚举的属性
  3. undefinednull无法转成对象,它们不能作为Object.assign参数,但是可以作为源对象
  4. 属性名为Symbol 值的属性,可以被Object.assign拷贝。
    <a name="tt1xh"></a>

<br />

<a name="M21mM"></a>

方法二:Array.prototype.slice

实现原数组的浅拷贝

var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[0] = 2;
console.log(a); // [ 1, 3, 5, { x: 1 } ];
console.log(b); // [ 2, 3, 5, { x: 1 } ];

// 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变
// 说明a和b在栈内存中引用地址并不相同。
var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[3].x = 2;
console.log(a); // [ 1, 3, 5, { x: 2 } ];
console.log(b); // [ 1, 3, 5, { x: 2 } ];
// 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变
// 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。

<a name="MeAAK"></a>

<br />

<a name="i7CEU"></a>

方法三:Array.prototype.concat

let array = [{a: 1}, {b: 2}];
let array1 = [{c: 3},{d: 4}];
let array2=array.concat(array1);
array1[0].c=123;
console.log(array2);// [ { a: 1 }, { b: 2 }, { c: 123 }, { d: 4 } ]
console.log(array1);// [ { c: 123 }, { d: 4 } ]

<a name="e9pGO"></a>

<br />

<a name="6nDua"></a>

方法四:...扩展运算符

语法:var cloneObj = { ...obj };

var a = [ 1, 3, 5, { x: 1 } ];
var b = {...a};
b[0] = 2;
console.log(a); // [ 1, 3, 5, { x: 1 } ];
console.log(b); // [ 2, 3, 5, { x: 1 } ];

// 从输出结果可以看出,浅拷贝后,数组a[0]并不会随着b[0]改变而改变
// 说明a和b在栈内存中引用地址并不相同。
var a = [ 1, 3, 5, { x: 1 } ];
var b = {...a};
b[3].x = 2;
console.log(a); // [ 1, 3, 5, { x: 2 } ];
console.log(b); // [ 1, 3, 5, { x: 2 } ];
// 从输出结果可以看出,浅拷贝后,数组中对象的属性会根据修改而改变
// 说明浅拷贝的时候拷贝的已存在对象的对象的属性引用。

<a name="POpRe"></a>

其他方法:

//浅拷贝实现
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
  var dst = {};
  for (var prop in src) {
    if (src.hasOwnProperty(prop)) {
      dst[prop] = src[prop];
    }
  }
  return dst;
}
shallowObj.arr[1] = 5;
obj.arr[1]   // = 5

<br />

<a name="T4oun"></a>

深拷贝

<br />深拷贝开辟一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性<br /><br />注意:深拷贝对对象中的子对象进行递归拷贝,拷贝前后两个对象互不影响<br />
<a name="RwkJM"></a>

实现方法:

<a name="njWEd"></a>

方法一:JSON.parse(JSON.stringify())

  • JSON.stringify()是前端开发过程中比较常用的深拷贝方式。
  • 原理是把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象
let arr = [1, 2, {name: ' duoduo'}];
let newarr = JSON.parse(JSON.stringify(arr));

newarr[2].name = 'nana'; 

console.log(newarr); // [ 1, 2, { username: 'nana' } ]
console.log(arr);    // [ 1, 2, { username: 'duoduo' } ]

JSON.stringify()实现深拷贝注意点

  1. 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
  2. 无法拷贝不可枚举的属性,无法拷贝对象的原型链
  3. 拷贝Date引用类型会变成字符串
  4. 拷贝RegExp引用类型会变成空对象
  5. 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
  6. 无法拷贝对象的循环应用(即obj[key] = obj)

方法二:jquery 的 $.extend

var $ = require('jquery');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);

<a name="gm4ie"></a>

赋值、深拷贝、浅拷贝

浅拷贝和****深****拷贝****区别<br />浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级<br />

fuzhi.png
<br />**<br />
<br />
<br />

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,226评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,509评论 3 405
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,523评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,181评论 1 302
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,189评论 6 401
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,642评论 1 316
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,993评论 3 431
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,977评论 0 280
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,527评论 1 326
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,547评论 3 347
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,661评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,250评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,991评论 3 340
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,422评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,571评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,241评论 3 382
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,737评论 2 366

推荐阅读更多精彩内容