javascript值传递与引用传递

版权声明:欢迎转载 https://blog.csdn.net/feinifi/article/details/84701957

javascript中,变量类型分为基本类型和对象类型,基本类型有以下几种:string,number,boolean,null,undefined,对象类型就是object,object又分为object,array,function。基本类型是值传递,对象类型是引用传递。具体来说,就是基本类型a=1,赋给另一个变量b=a,在操作b的时候,a的值不会随着b的变化而变化。对象类型就不一样了,如a = [1,2],当我们赋值给b=a,对b进行操作,b[0]=2,这时候a也跟着变化a=[2,2]。这就是值传递与引用传递的区别。下面我们看具体的示例:

$(function() {
      var a = {name:"aa"};
      var b = ["a","b","c"];
      var c  = a;
      c.id = 101;
      console.log(a); //{name:"aa",id:101}
      var d = b;
      d.push("d");
      console.log(b);//["a","b","c","d"]
      var e = 12;
      var f = e;
      f = f+1;
      console.log(e);//12
});

运行结果如下:

基本类型,值传递,这个没什么好说,但是对象类型引用传递,原因是两个变量公用一个内存,在操作任意变量对象的时候,它们的值都是会发生变化的。那么问题来了,如果需要做到不改变原始变量的值,怎么办,这里就需要解决一个内存问题,就是怎么把两个变量变为两个内存中的地址,而不是共用一块内存,这里就需要用到拷贝。

js中的拷贝分为浅拷贝和深拷贝,所谓浅拷贝就是在变量赋值过程中,只拷贝一级变量,比如a={name:"aa",id:101},b=simpleclone(a),那么name,id都会拷贝过去,当我们修改name,id的值,不会影响到a。

$(function() {
      function simpleclone(a){
          var res = {};
          for (var i in a){
              res[i] = a[i];
          }
          return res;
      }
      var a = {name:"aa",id:101};
      var b = simpleclone(a);
      b.id = 102;
      console.log(a,b);
});

运行结果如下:

从结果看出,b经过改变,a的值没有发生变化,赋值之后,b与a的关系切断了。基本达到了我们的要求。但是浅拷贝有个问题,就是只是拷贝一级变量,如果一个变量内部有一个嵌套的对象,那么浅拷贝就失去了作用。

$(function() {
    function simpleclone(a){
        var res = {};
        for (var i in a){
            res[i] = a[i];
        }
        return res;
    }
    var a = {name:"aa",id:101,address:{postcode:100085,detail:"1-3-602"}};
    var b = simpleclone(a);
    b.id = 102;
    console.log(a,b);
    b.address.postcode = 100000;
    console.log(a,b);
});

运行结果:

当改变一级变量id=102时,a,b的id是不相同的,当我们改变b.address.postcode=100000时,结果a.address.postcode也发生了变化,这就有问题了,浅拷贝不能解决变量嵌套 变量的问题。这就需要深拷贝来解决了。

深拷贝的思路就是在浅拷贝的基础上做了一个判断,如果是对象变量,即变量嵌套变量,那么就需要使用递归来拷贝。

$(function() {
    function deepclone(a) {
        var res = {};
        for(var i in a){
            if(typeof a[i]=="object"){
                res[i] = deepclone(a[i]);
            }else{
                res[i] = a[i];
            }
        }
        return res;
    }
    var a = {name:"aa",id:101,address:{postcode:100085,detail:"1-3-602"}};
    var b = deepclone(a);
    b.id = 102;
    b.address.postcode = 100000;
    console.log(a,b);
});

运行结果:(这里的递归拷贝不是一个完美的方法,没有考虑属性是数组的情况)

深拷贝的结果是当b=deepclone(a)之后,对b做的任何改变,都不会影响a,这样就完全解决了对象引用传递带来的问题。深拷贝的实现方式,除了递归拷贝之外,还有几种方式,这里jQuery提供了一种方法$.extend(true,b,a);该方法的第一个参数如果是false,那么就是浅拷贝,只有为true时,才是深拷贝。第二个参数是拷贝前的结果,一般是一个空对象,第三个参数是需要拷贝的对象。 还有一种实现方式就是使用JSON对象提供的方法。

function deepclone(a) {
    //return $.extend(true,{},a);
    var tmp = JSON.stringify(a);
    return JSON.parse(tmp);
}

猜你喜欢

转载自blog.csdn.net/feinifi/article/details/84701957
今日推荐