zoukankan      html  css  js  c++  java
  • js按值传递还是按引用传递?

    js和其他大部分语言一样,有基本类型和引用类型。因此访问变量就有按值按引用两种方式,但是传参的时候却只能按值传递。基本类型作为参数时按值传递自然无可厚非,但引用类型作为参数也按值传递就让人有点困惑了。

    看下面这个例子:

     1 function setName(obj){
     2 
     3   obj.name = "Sim";
     4 
     5 }
     6 
     7 var person = new Object();
     8 
     9 setName(person);
    10 
    11 alert(person.name);  //"Sim"

    以上代码创建了一个名为person的对象,并且将其作为参数传给了setName函数。我们在函数内部给传进来的对象添加了一个name属性并赋值,之后在函数外部访问person.name,会弹出"Sim"。一般我们都说,若是按值传递的话,形参在函数内的变化不会影响到实参的变化,但这个例子中,函数内部给形参加上的属性在实参中也有此属性。这会让人产生一种误解,感觉引用类型传参貌似是按照引用传递的啊!

    下面再给出一个例子:

    var obj1 = {
      value:'111'
    };
     
    var obj2 = {
      value:'222'
    };
     
    function changeStuff(obj){
      obj.value = '333';
      obj = obj2;
      return obj.value;
    }
     
    var foo = changeStuff(obj1);
     
    console.log(foo);// '222' 参数obj指向了新的对象obj2
    console.log(obj1.value);//'333'

    上面例子打印出了形参obj和实参obj1的value值我们可以清楚的看到,这两个value值并不一样,因此可以证明引用类型的参数并非是按照引用传递的。

    至于为什么会出现这种情况,那就有必要来理解一下js中的数据存储与访问的机制了。

    声明变量时的内存分配

    基本类型:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

    引用类型:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

    复制变量时的不同:

    基本类型:在将一个保存着原始值的变量复制给另一个变量时,会将基本类型的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。

    引用类型:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)
     
    在清楚了这些之后,我们再来结合之前的那个例子来看:
    可以看到之所以给形参加上属性之后,实参也会带有此属性。那是因为实参,形参都是指向储存在堆内存中的对象的指针。我们改变的其实是堆内存中的对象的属性,obj和obj1都没有发生改变。但当执行了obj = obj2之后,相当于将obj指向了obj2所指向的value值为‘222'的对象。
    搞清楚了这些,估计你就能理解为什么引用类型的传参方式是按值传递了吧!
  • 相关阅读:
    原生JS实现四舍五入
    js获取table checkbox选中行的值.mdjs获取table checkbox选中行的
    springcloud eureka server 检测 eureka client 状态
    jQuery HTML / CSS 方法
    jQuery 效果方法
    jQuery 事件方法
    jQuery 选择器
    Mybatis Generator配置详解
    netty 文件传输
    C++虚表的奇葩用法
  • 原文地址:https://www.cnblogs.com/Likebard/p/5860279.html
Copyright © 2011-2022 走看看