美文网首页
JS传参是按值传递还是按引用传递?

JS传参是按值传递还是按引用传递?

作者: 帅气滴糟老头 | 来源:发表于2018-09-07 16:39 被阅读0次

    发现对js传参是值传递还是引用传递这个问题的认识不是很清晰,在这里做下探究。


    首先要清楚的是,什么是按值传递?什么又是按引用传递?
    值传递(call by value):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
    引用传递(call by refrence):也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。

    两种传递方式都有各自的问题:按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低;按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。

    基本类型按值传递

    基本类型包括:Undefined,Null,Boolean,Number、String
    下面直接看例子:

    var a = 1;
    function foo(val) {
      val = 2;
    }
    foo(a);
    console.log(a);  // 输出结果为:1
    

    分析以上代码,a是基本类型,存储在栈中,函数foo的的形参只是变量a的拷贝,调用函数时会在栈中新建一个变量val,并将变量a的值赋值给变量val,但是变量val和变量a并无关联,所以对变量val的修改操作并不会影响到变量a。

    引用类型传递方式

    引用类型包括:Object,Array,Date,RegExp,Function,......
    我们先看下面的代码:

    var person = {name:'MJ'};
    function foo(obj) {
      obj.name = 'EP';
    }
    foo(person);
    console.log(person.name); // 输出结果为:EP
    

    对象person被修改了!这说明obj跟person指向的是同一个对象,可以肯定不是按值传递的了,那么就是引用传递了吗?从这个例子来看确实很像,我们再对上面的例子做下修改,如下:

    var person = {name: "MJ"};
    function foo(obj) {
      obj = new Object(); // 修改部分
      obj.name = "EP";
    }
    foo(person);
    console.log(person.name); // 输出结果为:MJ
    

    输出结果是MJ,也就是说person对象并未被修改,如此可以确定,js的引用类型也不是按引用传递。既不是按值传递,又不是按引用传递,那是按什么传递呢?

    按共享传递(call by sharing):

    准确的说,JS中的基本类型按值传递,引用类型按共享传递(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。
    该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。
    接下来我们分析下上面的代码,为什么person没有被修改?
    我们都知道对象保存在堆中,person持有堆中对象的引用,在调用foo函数时,函数接收的实际是person持有的对象(下面称之为原对象)引用的副本,这样obj和person都指向了同一个地方(也就是原对象在堆中存放的地址),而函数中的obj = new Object()操作其实是在堆中创建了一个新对象,并让obj持有该对象的引用,这样obj与原对象之间的关系就断开了,转而与新对象建立了关系,所以对obj的修改并不会影响到原对象。


    总结

    在JS中,基本类型按值传递,引用类型按共享传递

    相关文章

      网友评论

          本文标题:JS传参是按值传递还是按引用传递?

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