继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

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

Cats萌萌
关注TA
已关注
手记 275
粉丝 50
获赞 304

原文链接

值(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); // unchanged13 console.log(obj2.item); // unchanged14 changeStuff(num, obj1, obj2);15 console.log(obj1.item); // changed16 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!


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP