视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript参数传递中值和引用的一种理解的详细介绍
2020-11-27 20:24:30 责编:小采
文档
值(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。

 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!

下载本文
显示全文
专题