前言


js数据类型次要分根本数据类型和援用数据类型。前者包含Number,String等,后者次要是Object,因而以下会针对不同的数据类型来剖析,同时须要一点js的内存的常识,以下先简要提一下

js内存

js内存,或者说大部分语言的内存都分为栈和堆。根本数据类型的变量值调配在栈上,援用数据类型的变量值调配在堆上,栈中只是存储具体堆中对象的地址。

赋值


对于根本数据类型,赋值操作是拷贝,即新旧变量不会相互影响。

var a = 1;var b = a;b = 2;console.log(b); // 2

对于援用数据类型,赋值操作只是在栈中新增一个指向堆中对象的变量,即复制援用地址。新旧变量之间会相互影响,即在新变量上扭转对象值,旧变量对应值也会扭转。

var a = {    name: "mike"};var b = a;b.name = "jack";console.log(a); // {name: "jack"}

浅拷贝


对于根本数据类型和不具备嵌套对象的数据,均是拷贝操作,新旧变量之间不会相互影响。

var a = {    name: "mike"};var b = {};b.name = a.name;b.name = "jack";console.log(a) // {name: "mike"}

然而对于具备嵌套对象的数据,浅拷贝只拷贝第一层对象,深层次的值依然是复制援用地址。

var a = {    name: "mike",    language: {        first: "english",        second: "chinese"    }};var b = {};b.name = a.name;b.name = "jack";b.language = a.language;b.language.first = "japanese"console.log(a) // { language : {first: "japanese", second: "chinese"}}

js实现浅拷贝,思维:遍历target的每个属性,将起属性名和值赋值给新变量。
如果你明确了赋值的含意,那么在代码的第四行,当此时的target[key]的值是对象的时候,通过赋值赋予新变量,实质上是复制援用数据类型在堆中的地址,就不难理解为什么浅拷贝对于是否是嵌套对象的有不同后果了。

function shallowCopy(target) {    let result = {};    for (const key in target) {        result[key] = target[key];    }    return result;}

深拷贝


深拷贝是完完全全的拷贝,新旧变量之间不会相互影响。
对于参数是否是对象有不同的解决办法,如果是对象,对于对象的每个属性和值赋值而后递归解决; 否则间接返回。

function clone(target) {    if (typeof target === "object") {        //判断是否是数组        let result = Array.isArray(target)? [] : {};        for (const key in target) {            result[key] = clone(target[key]);        }        return  result;    } else {        return target;    }}

参考

深拷贝实现