ホームページ  >  に質問  >  本文

函数传递 - JavaScript中函数的参数传递方式都是按值传递

函数传递方式

JavaScript中函数的参数传递方式都是按值传递,没有按引用传递,应该怎么理解??

“能不能举个例子”

补充:保存引用的对象(比如数组,它是按照引用传递的又该怎么理解)

function add(arr,num){
    for(var i=0; i<arr.length; i++){
        arr[i]+= num;
    }
}
var arr1 =[1,2,3,4,5];
add(arr1,5);
console.log(arr1);//[6, 7, 8, 9, 10]
PHP中文网PHP中文网2768日前734

全員に返信(8)返信します

  • 迷茫

    迷茫2017-04-10 15:42:36

    楼上的回答中,@kikong 的回答是最靠谱的。

    当传递原始类型值给形参时,传递的就是原始值本身。
    当传递引用类型值给形参时,传递的是一个指针(一个特殊的值)。

    这就是所谓的 JS 中的按值传递

    其实吧,JavaScript 的参数传递涉及两组核心概念:

    1. 按值传递和按共享传递(call by value VS call by sharing

    2. 重新绑定和变异 (rebinding VS mutation

    参数传递的本质其实是一个隐式赋值,赋值运算(=)发生了什么,参数传递就发生了什么。

    var num1 = 5
    var num = num1

    num1 保存着数字类型值 5,将 num 赋值为 num1num就保存了数字 5。这是按值传递。

    var arr1 = [1, 2, 3, 4, 5]
    var arr = arr1

    arr1 保存一个引用类型值,也可以理解为 arr1 指向数组 [1, 2, 3, 4, 5]的内存地址。将 arr 赋值为 arr1arr 也就指向了该数组的内存地址。这是按共享传递(两个变量共享该对象的内存地址)。

    var arr1 = [1, 2, 3, 4, 5]
    var arr = arr1
    arr = [2, 3, 4, 5, 6]

    arr 原本与 arr1 一起指向数组 [1, 2, 3, 4, 5] 的内存地址,但通过另一个赋值语句,使 arr 重新指向了数组 [2, 3, 4, 5, 6] 的内存地址。这是重新绑定。

    var arr1 = [1, 2, 3, 4, 5]
    var arr = arr1
    arr1.push(6)
    console.log(arr1.length) // => 6
    console.log(arr.length)  // => 6

    任何对 arr1arr 的修改都是对其所指向对象的修改。这是 mutation。

    这里尤其需要注意的是 rebinding。对 arr 重新赋值之后,arr1arr 已经指向了不同的内存地址,两者已经断开联系。

    在你的例子中,

    function add(arr,num){
        for(var i=0; i<arr.length; i++){
            arr[i]+= num;
        }
    }
    var arr1 =[1,2,3,4,5];
    add(arr1,5);
    console.log(arr1);//[6, 7, 8, 9, 10]

    在执行 add(arr1, 5) 时,传参完成的是隐式的赋值操作(即,arr = arr1, num = 5),其中传参给 arr 是 按共享传递,传参给 num 是按值传递

    在函数体内修改 arr (arr[i] += num),是 mutation 操作,所以即便 arr 在随后被销毁了,通过 arr1 也能观察到变更。

    返事
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 15:42:36

    javascript中的参数传递都采用 按值传递的方式
    对于对象来说,这个值是指对象的内存地址
    对基本类型,这个值是原始值

    =======

    function add(arr,num){
        console.log(arr);//[1,2,3,4,5];
        //arr被重新赋值前和arr1的相同
        arr=[5,6,7,8,9];//arr被重新赋值,指向的地址不同,但不会影响arr1的指向,也就是其地址信息
        for(var i=0; i<arr.length; i++){
            arr[i]+= num;
        }
        console.log(arr);//[10, 11, 12, 13, 14]
    }
    var arr1 =[1,2,3,4,5];
    add(arr1,5);
    console.log(arr1);//[1, 2, 3, 4, 5]
    

    返事
    0
  • 怪我咯

    怪我咯2017-04-10 15:42:36

    1、按值传递:
    按值传递就是将变量先复制一份,然后将复制的变量传入函数,如下面函数,先将num复制,然后再将复制的值传入add函数,执行下面函数就很明了了。
    var num=10;
    function add(num){
    num+=10;
    return num;
    }
    console.log("这是add方法返回的值 "+add(num));//这是add方法返回的值 20
    console.log("这是原始的num "+num);//这是原始的num 10
    2、按引用传递
    按引用传递思想和按值传递一样,先将对象的引用复制一份,然后再将所复制的引用传入函数;不同的是,这两个引用都指向同一个对象。来看一下面的一段代码:
    function person(){
    this.name="小明";
    this.age=23;
    }
    p1=new person();
    p2=new person();
    function editName(person){
    person.name="小红";
    }
    console.log(p1.name);//小明
    editName(p1);
    console.log(p1.name);//小红
    注意:不是说可以改变对象的值就是说明是按引用传递,例如以下代码:
    function chengeName(p){
    p=new person();
    p.name="小小";
    }
    p2=new person();
    console.log(p2.name);//小明
    chengeName(p2);
    console.log(p2.name);//小明
    这里p2的name虽然没有改变,但它也是属于按引用传递的

    返事
    0
  • 巴扎黑

    巴扎黑2017-04-10 15:42:36

    js中函数参数都是按值传递的,即使函数局部改变引起了全局的改变。javascript高级程序设计里是这么说的,可是js里对象哪里有值传递啊。。。
    直接传值的话,又哪来的深复制浅复制啊。搞不懂了
    function setName(obj) {
    obj.name = 'obj';
    obj = new Object();
    obj.name = 'obj2';
    }

    var person = new Object();
    setName(person);
    console.log(person.name);//obj

    返事
    0
  • PHP中文网

    PHP中文网2017-04-10 15:42:36

    http://www.zhihu.com/question/27114726
    http://www.zhihu.com/question/25336993

    返事
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:42:36

    传递参数:所有函数的参数都是按值传递的。基本类型值的传递如同基本类型变量的复制,而引用类型值的传递,如同引用类型变量的复制。

    复制变量值:基础类型会创建一个新值,把值复制到新位置,之后彼此独立。引用类型会复制指针,新老变量(复制和被复制的变量)引用同一个对象,改变其中一个,就会影响另一个。

    例子可以参考js高级程序设计第三版4.1.3

    返事
    0
  • 黄舟

    黄舟2017-04-10 15:42:36

    把引用类型的变量想成一堆指针,就是全按值传递。

    返事
    0
  • ringa_lee

    ringa_lee2017-04-10 15:42:36

        var foo = {
            bar: function() { return this.baz; },
            baz: 1
        };
    
        (function(){
            return typeof arguments[0]();//"undefined"
        })(foo.bar);

    你看这个例子,如果是传递引用,那么foo.bar应该会被当作函数传进去,后面的typeof就不会是undefined了。对吧。

    返事
    0
  • キャンセル返事