zoukankan      html  css  js  c++  java
  • JavaScript 函数参数是传值(byVal)还是传址(byRef)?

    对于“JavaScript 函数参数是传值(byVal)还是传址(byRef)”这个问题,普遍存在一个误区:number,string等“简单类型”是传值,Number, String, Object, Array等“复杂类型”是传址。
    这样不对吗?为什么会有这样的误区?看一下这两段代码:

    //造成传值假象的代码
    function modifyLikeByVal(x){
      x = 1;
      console.log('x = %d', x);
    }
    var x = 0;
    console.log('x = %d', x); // 输出 x = 0
    modifyLikeByVal(x);  // 输出 x = 1
    console.log('x = %d', x); // 输出 x = 0   x没变!
    //造成传址假象的代码
    function modifyLikeByRef(x){
      x[0] = 4;
      x[1] = 5;
      x[2] = 6;
      console.log('x = [ %s ]', x.join(', '));
    }
    var x = [1, 2, 3];
    console.log('x = [ %s ]', x.join(', ')); // 输出 x = [ 1, 2, 3 ]
    modifyLikeByRef(x);  // 输出 x = [ 4, 5, 6 ]
    console.log('x = [ %s ]', x.join(', ')); // 输出 x = [ 4, 5, 6 ]   x变了!

    于是,由以上代码得出结论,“简单类型”作为参数是传值(byVal)的,“复杂类型”作为参数是传址(byRef)的。

    问题出在哪呢?

    仔细观察两个函数,就可以发现一点:
    在byVal中,是直接修改了参数x: x = 1;
    而byRef中,是修改参数x的成员: x[0] = 4; x[1] = 5; x[2] = 6;

    本人由此得出猜想:在JavaScript中,所有的变量或成员,都是一个指针,在修改变量或成员值的时候,其实是修改了该指针的地址

    这样上面的代码就可以得到解释了:

    在“byVal”中:

    global {  // 表示全局作用域,下面的表示函数作用域
      var x = 0;  // 初始化指针x并指向数字0
        fun(x) {
          x = global.x; // 传入参数global.x; fun域的x指针地址与global域的x指针地址一样指向数字0
          x = 1; // 修改fun域的x指针地址,指向数字1;
        } // fun 域结束,global域中的x指针没改变
    }

    在“byRef”中:

    global {  // 表示全局作用域,下面的表示函数作用域
      /*
        初始化指针x并指向数组[1, 2, 3]
        其实是x的三个成员0, 1, 2,分别指向1, 2, 3;
      */
      var x = [1, 2, 3];  
        fun(x) {
          x = global.x; // 传入参数global.x; fun域的x指针地址与global域的x指针地址一样指向数组[1, 2, 3]
          /*
           在fun域中的x没有再被改变
           紧接着修改fun域中的x(也就是global.x)三个成员指针的指向
          */
          x[0] = 4;
          x[1] = 5;
          x[2] = 6;
        } // fun 域结束,global域中的x指针没改变,但其三个成员指针被改变了,于是就看到我们输出的结果
    }

    那这段代码怎么解释呢???

    (function(a, b){
        arguments[0] = 1;
        b = 2;
        console.log(arguments, a, b);
    })(-1, -2);

    只能说a, b...,是arguments[0],...[n]的别名了。

    如果有不对的地方,请指出来,谢谢。

    如果有更好的解释,欢迎大家分享。

  • 相关阅读:
    ZTree id值太大,ZTree没有生成树,ZTree的id值过大
    Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装
    Linux Redis 重启数据丢失解决方案,Linux重启后Redis数据丢失解决方
    Linux Redis自动启动,Redis开机启动,Linux Redis设置开机启动
    Linux Redis安装,Linux如何安装Redis,Linux Redis自动启动,Redis开机启动
    springJdbc in 查询,Spring namedParameterJdbcTemplate in查询
    Sublime的插件Color Highlighter的安装方法
    Sublime的Package Control安装方法
    JavaScript实现最简单的拖拽效果
    css抠图之background-position-背景定位
  • 原文地址:https://www.cnblogs.com/arliang/p/Arguments_Passing_ByVal_or_ByRef_in_JavaScript.html
Copyright © 2011-2022 走看看