JavaScript值传递 or 引用传递?

作者: 岛在深海处 | 来源:发表于2018-10-27 17:14 被阅读6次

    对于函数的值传递和引用传递一直有点模糊理解。今天正好有空来扒一扒,首先看下关于这两个词的解释:

    值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 ——百度百科

    引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 ——百度百科

    从定义来看,不管是值传递还是引用传递,都是针对参数来说的,也就是说只在变量当成参数传给函数时,才适用是值传递还是引用传递的讨论范围。

    我们来看段代码:

    function setName(arg){
      arg.name = "Nicholas";
      arg = new Object();//将函数局部变量obj指向另一个新的变量
      arg.name = "Greg";
    }
    var person = new Object();
    setName(person);//传递栈中的指针值
    console.log(person.name);//Nicholas
    

    用堆栈图表示:


    函数的引用传递.png

    通过堆栈图发现,javaScript在传递参数的时候实际上是把实际参数的地址传递到函数中。这跟我之前的理解就有点冲突了,之前没理清值传递与引用传递的概念,一直认为函数在传递参数的时候都是值传递。那照这样说,javaScrpit参数到底存不存在真正的值传递呢?

    以我个人理解来看,并不存在,因为就算是基本数据类型当参数内存中也没必要额外复制一份地址,因为基本类型的值是不可变的。

    我们来看以下代码:

    function addTen(arg) {
       arg = arg + 10;
       return arg;
    }
    var count = 20;
    var result = addTen(count);
    console.log(count); // 20
    console.log(result); // 30
    

    从节约内存的角度来讲,应该是直接将参数arg指向实际参数count的地址,当有新值赋给arg时才将arg指向新值的地址。而不是一开始就在内存中造两个20。

    由于基本类型的值是不变的,我们无法直接修改其值,所以只能用赋值符号("=")来赋予新的值。旧值如果没有被其他变量引用,就会被回收。

    对应的堆栈图我们画出来:

    基本类型参数传递.png

    我们把javaScript参数分为两类:

    基本类型与引用类型

    基本类型:String,Number,Boolean,Null,Undefined。
    引用类型:Array、Object、Function、Date等有多个值构成的可变长度的复杂类型。

    网上很多文章都把基本类型的函数传参解释为值传递,这样理解其实也是可以的,结果都一样,本着节省内存的角度,我认为引用传递更合理。

    关于JavaScript变量赋值在内存中存储的问题可以看这篇文章:
    javaScript变量在内存中的存储问题

    相关文章

      网友评论

      • 伊泽瑞尔灬:大概懂了,传一个string,number就是值传递,函数里面改变参数对原值没有影响。
        传入Map或者array,就是引用传递,函数里面改变参数的值,会对原对象有影响,除非new一个。
        岛在深海处:基本数据类型不可变,所以任何对基本数据的操作都不能影响原值。而其他类型数据都是可变的,除了赋值符号以外的任何改变参数的操作都会改变原值

      本文标题:JavaScript值传递 or 引用传递?

      本文链接:https://www.haomeiwen.com/subject/gaqdtqtx.html