龙空技术网

JavaScript赋值、浅拷贝和深拷贝

知识探索星球 403

前言:

此时姐妹们对“phpjs变量赋值”都比较关切,看官们都想要知道一些“phpjs变量赋值”的相关资讯。那么小编同时在网络上搜集了一些关于“phpjs变量赋值””的相关内容,希望看官们能喜欢,你们一起来学习一下吧!

赋值

赋值是将某一数值或对象赋给某个变量的过程。

基本数据类型:赋值,赋值之后两个变量互不影响引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响

对基本类型进行赋值操作,两个变量互不影响。

let a = "muyiy";let b = a;console.log(b);// muyiya = "change";console.log(a);// changeconsole.log(b);// muyiy

对引用类型进行赋址操作,两个变量指向同一个对象,改变变量 a 之后会影响变量 b,哪怕改变的只是对象 a 中的基本类型数据。

let a = { name: "muyiy", book: { title: "You Don't Know JS", price: "45" }}let b = a;console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "45"}// } a.name = "change";a.book.price = "55";console.log(a);// {// 	name: "change",// 	book: {title: "You Don't Know JS", price: "55"}// } console.log(b);// {// 	name: "change",// 	book: {title: "You Don't Know JS", price: "55"}// }

通常在开发中并不希望改变变量 a 之后会影响到变量 b,这时就需要用到浅拷贝和深拷贝。

浅拷贝

什么是浅拷贝

创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

浅拷贝使用场景

Object.assign()

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

let a = { name: "muyiy", book: { title: "You Don't Know JS", price: "45" }}let b = Object.assign({}, a);console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "45"}// } a.name = "change";a.book.price = "55";console.log(a);// {// 	name: "change",// 	book: {title: "You Don't Know JS", price: "55"}// } console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "55"}// }

上面代码改变对象 a 之后,对象 b 的基本属性保持不变。但是当改变对象 a 中的对象 book 时,对象 b 相应的位置也发生了变化。

展开语法 Spread

let a = { name: "muyiy", book: { title: "You Don't Know JS", price: "45" }}let b = {...a};console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "45"}// } a.name = "change";a.book.price = "55";console.log(a);// {// 	name: "change",// 	book: {title: "You Don't Know JS", price: "55"}// } console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "55"}// } 

通过代码可以看出实际效果和 Object.assign() 是一样的。

Array.prototype.slice()

slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。

let a = [0, "1", [2, 3]];let b = a.slice(1);console.log(b);// ["1", [2, 3]]a[1] = "99";a[2][0] = 4;console.log(a);// [0, "99", [4, 3]]console.log(b);// ["1", [4, 3]]

可以看出,改变 a[1] 之后 b[0] 的值并没有发生变化,但改变 a[2][0] 之后,相应的 b[1][0] 的值也发生变化。说明 slice() 方法是浅拷贝,相应的还有concat等,在工作中面对复杂数组结构要额外注意。

深拷贝

什么是深拷贝

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。

深拷贝使用场景

JSON.parse(JSON.stringify(object))

let a = { name: "muyiy", book: { title: "You Don't Know JS", price: "45" }}let b = JSON.parse(JSON.stringify(a));console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "45"}// } a.name = "change";a.book.price = "55";console.log(a);// {// 	name: "change",// 	book: {title: "You Don't Know JS", price: "55"}// } console.log(b);// {// 	name: "muyiy",// 	book: {title: "You Don't Know JS", price: "45"}// } 

完全改变变量 a 之后对 b 没有任何影响,这就是深拷贝的魔力。

我们看下对数组深拷贝效果如何。

let a = [0, "1", [2, 3]];let b = JSON.parse(JSON.stringify( a.slice(1) ));console.log(b);// ["1", [2, 3]]a[1] = "99";a[2][0] = 4;console.log(a);// [0, "99", [4, 3]]console.log(b);// ["1", [2, 3]]

1、会忽略 undefined

2、会忽略 symbol

3、不能序列化函数

4、不能解决循环引用的对象

5、不能正确处理new Date()

6、不能处理正则

undefined、symbol 和函数这三种情况,会直接忽略。

let obj = { name: 'muyiy', a: undefined, b: Symbol('muyiy'), c: function() {}}console.log(obj);// {// 	name: "muyiy", // 	a: undefined, // b: Symbol(muyiy), // c: ƒ ()// }let b = JSON.parse(JSON.stringify(obj));console.log(b);// {name: "muyiy"}
循环引用情况下,会报错。
let obj = { a: 1, b: { c: 2, 		d: 3 }}obj.a = obj.b;obj.b.c = obj.a;let b = JSON.parse(JSON.stringify(obj));// Uncaught TypeError: Converting circular structure to JSON
new Date 情况下,转换结果不正确。
new Date();// Mon Dec 24 2018 10:59:14 GMT+0800 (China Standard Time)JSON.stringify(new Date());// ""2018-12-24T02:59:25.776Z""JSON.parse(JSON.stringify(new Date()));// "2018-12-24T02:59:41.523Z"

解决方法转成字符串或者时间戳就好了。

let date = (new Date()).valueOf();// 1545620645915JSON.stringify(date);// "1545620673267"JSON.parse(JSON.stringify(date));// 1545620658688
正则情况下
let obj = { name: "muyiy", a: /'123'/}console.log(obj);// {name: "muyiy", a: /'123'/}let b = JSON.parse(JSON.stringify(obj));console.log(b);// {name: "muyiy", a: {}}
总结

原文:

标签: #phpjs变量赋值 #html赋值标签