本人小白,初接触JS在此,仅仅是将自己学到的认识到的,写在这里做个笔记。

在JS中赋值的主要有两种类型:

  (1)直接将数值类进行复制

  (2)引用赋值,如下:

  

1 var obj = {
2    name:'xx'
3 }
4 
5 var o1 = obj1;
6 var o2  = o1;

  当我们修改o2.name 那么o1.name会随之发生改变。

  上述情况就说明o1,o2指向的是同一块内存区域。o1,o2拥有的只是一种类似指针的东西指向同一块内存区域。

那么来看看JS的复制。

(1)浅复制,在复制JS中‘object’,'array' 这类型的属性时,只是简单的复制引用,当我们的原始对象发生改变时,克隆过后的对象会跟着发生改变。类似与上面的情况。

1 function shallowClone(obj){
2     var newObj = {};
3     for(var attr in obj){
4         if(obj.hasOwnProperty(attr)){
5             newObj[attr] = obj[attr];
6         }        
7     }
8     return newObj;
9 }

  当我们尝试修改克隆对象时,会看到如下结果:

var obj = {a:1,arr:[2,3]};
var shallowObj = shallowClone(obj);
shallowObj.arr[0]=3;

  在ES6中,定义了一个方法Object.assign(..)

    第一个参数为目标对象target,后续的参数是一个或者多个源对象source。它会在源对象上迭代所有可枚举的,直接拥有的的key,将他们拷贝到目标对象(target)上。并且返回目标对象。

 

  所以,当我们操作JS对象,对其进行拷贝时,一定要注意,有可能你一不小心用到了浅复制,难么你在修改任何一个copy的时候会操成所有的copy发生改变。

(2)深复制,相对于浅复制来说,深复制是在浅复制的基础上,将被copy对象上的所有‘object’,'array'再进行一次浅复制。

  1)一种实现方式是采用JSON序列化、反序列化来实现。

 

if(Window.JSON){
    str = JSON.stringify(obj)//序列化对象
    newObj = JSON.parse(str);//还原
}

  这种方式必须保证对象是可以系列化成JSON的。

  2)在浅复制的基础上,当我们碰到'object"、“array”类型的数据,我们采用递归。

var parentObject = [];
function deepCopy(obj){

    var str,newObj = obj.constructor ===Array ? []:{}
    parentObject.push(obj)
    if (typeof obj != 'object'){
        return ;
        
    }else{
        for (var i in obj){
            var v = obj[i]
            if(parentObject.indexOf(v) > -1){
                throw Error("检测到循环引用")
            }else{
                newObj[i] = typeof obj[i] === 'object' ?    deepCopy(obj[i]):obj[i];
            }
            
        }
    }
    parentObject.pop();
    return newObj;
}

  此时,当我们再修改一个copy时,不会对原对象造成影响了。

var newO = deepCopy(myObject);
newO.b.c = false;

  上述的两种深复制方法都有缺陷,不能解决循环依赖的问题。方法二只能做出检测,方法一会直接堆栈益处。

循环依赖如下:

function antherFunction(){};
var antherObject = {
    c:true
};
var antherArray = [];
var myObject = {
    a:2,
    b:antherObject,
    c:antherArray,
    d:antherFunction
};
antherArray.push(antherObject,myObject);