• Javascript参数传递中值和引用的一种理解


    值(value)和引用(reference)是各种编程语言老生常谈的话题,js也不例外。

    我将剖析一个例子的实际运行过程,跟大家分享我对js参数传递中的值和引用的理解。

    参考官网数据类型的两种分类,本文将这两种分类简称为基本类型(boolean, null, undefined, string, number, symbol)和object类型。

    首先,用一个example 演示参数传递的应用:

    var obj = {};
    obj.inner = 10;
    
    var num = 10;
    var str = 'Hello';
    var boo = true;
    var oth = null;
    var und = undefined;
    var sym = Symbol('foo');
    
    function passingobject(myobj){
        myobj.inner  = 1 + myobj.inner ; 
    }
    
    function passingvalue(myvalue){
      switch(typeof myvalue){
        case 'number':
            myvalue = myvalue + 1;
            break;
          case 'string':
            myvalue = 'I am a new string now!';
            break;
          case 'boolean':
            myvalue= false;
            break;
          default:
            myvalue = 'Null, Undefined, or Symbol';
         }
      }
    
      console.log("before num = " + num);  // before num = 10
      passingvalue(num);
      console.log("after num = " + num);  // after num = 10
      console.log("before str = " + str); // before str = Hello
      passingvalue(str);
      console.log("after str = " + str);  // after str = Hello
      console.log("before boo = " + boo); // before boo = true
      passingvalue(boo);
      console.log("after boo = " + boo);  // after boo = false
      console.log("before oth = " + oth); // before oth = null
      passingvalue(oth);
      console.log("after oth = " + oth);  // after oth = null
      console.log("before und = " + und); // before und = undefined
      passingvalue(und);
      console.log("after und = " + und);  // after und = undefined
      console.log(sym); // Symbol(foo)
      passingvalue(sym);
      console.log(sym); // Symbol(foo)
      console.log("before obj.inner = " + obj.inner); // before obj.inner = 10
      passingobject(obj); // after obj.inner = 11
      console.log("after obj.inner = " + obj.inner);

    从example 1 的结果似乎可以总结出以下两条结论:

    1. 传递的数据类型为基本类型(number, string boolean, null, undefined, symbol),在参数传递过程中,函数内部对传递值的操作并不影响原始值。

    2. 传递的数据类型为object, 在参数传递过程中,函数内部对传递值的操作会导致原始值的改变。

    然而, 有没有其他特殊情况呢?

    有一种在stackoverflow讨论很火热的用法,跟结论二背道而行。example 2。 

    例子引自:http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

     1 function changeStuff(a, b, c)
     2 {
     3   a = a * 10;
     4   b.item = "changed";
     5   c = {item: "changed"};
     6 }
     7 
     8 var num = 10;
     9 var obj1 = {item: "unchanged"};
    10 var obj2 = {item: "unchanged"};
    11 
    12 console.log(obj1.item); // unchanged
    13 console.log(obj2.item); // unchanged
    14 changeStuff(num, obj1, obj2);
    15 console.log(obj1.item); // changed
    16 console.log(obj2.item); // unchanged

    example 2中, obj2.item并没有被函数changeStuff改变。changeStuff内部同样改变了b、c的值,为什么obj1被改变了(L15)而obj2没有被改变呢?

    我用js的执行上下文对这种现象进行解释,如图。

    在js运行过程中,编辑器动态生成执行上下文(execution context),example 2中,首先生成global的执行上下文和changeStuff的执行上下文。

    执行到changeStuff(num, obj1, obj2)的时候, a, b, c指向参数num, obj1, obj2,a和num指向10, b跟obj1指向同一个值,c跟obj2指向同一个值。

    执行step 1的时候,对a重新赋值,为a赋值前的10倍,从此a与num毫无关系。

    执行step 2的时候,对b所指向的值的item属性进行重新赋值,这个赋值只改变了item的值, 而obj1和b仍然指向同一个值。

    执行step 3的时候,对c重新赋值,从此c与obj2再无瓜葛,因此即使c有一个叫item的属性,与obj2的item属性有着各自的值,并没有影响obj2.item。

    也就是说,js函数参数传递过程中,若函数内部对参数重新赋值,这个赋值过程不会影响原始变量的值。

    这也很好地解释了基本类型的参数变量(结论1)不会受影响的现象,基本类型的参数变量每一次改变都是一次全新赋值,对原始变量不会造成影响。

    总结

    在js函数传递中,当基本类型(number, string, boolean, null, undefined, symbol)变量作为参数传递时,函数内部对参数的任何操作都不会改变变量的值。

    当object类型变量作为参数传递时,函数内部对参数的操作会影响变量的值,除非函数内部对参数重新赋值(任何类型的值)。

    Thank you!

    Feel free to contact me if you have any question!

  • 相关阅读:
    阿里巴巴、腾讯、百度的面试问题笔知识汇总(两)
    ORM武器:NHibernate(三)五个步骤+简单对象CRUD+HQL
    SIGPIPE并产生一个信号处理
    Duanxx的Altium Designer学习:PCB试想一下,在目前的水平
    网络工程师课程---6、应用层(应用层的功能是什么)
    网络工程师课程---5、传输层(传输层常用协议有哪些)
    网络工程师课程---4、网络层(网关是什么)
    网络工程师课程---3、IP与路由器(ip地址的主要作用是什么)
    网络工程师课程---2、物理层和数据链路层(物理层的作用是什么)
    交换机与路由器与猫的区别与联系
  • 原文地址:https://www.cnblogs.com/haihai1203/p/5767931.html
Copyright © 2020-2023  润新知