JS中的函数参数传递到底是按值传递还是按引用传递

首先我们知道JS中的数据类型大致可以分为简单数据类型和复杂数据类型;
当我们声明一个变量并给它赋值时,可以赋给其简单值和复杂值(以下堆内存和栈内存的地址表示均随意取的,只是为了区分,不代表真实的内存地址);
针对简单数据类型:
例1

var simpleData1 = 18
var simpleData2 = simpleData1
simpleData2 =  19
console.log(simpleData1 )   //打印出18

以上例子的过程为:先给simpleData1 在栈内存中分配一个地址s101,里面保存数字18,然后将simpleData1赋给simpleData2 ,相当于紧接着在栈内存中又分配一个地址s102,里面同样保存数字18,这时再将s102中的内容变成19,这当然不会影响s101中的内容。
JS中的函数参数传递到底是按值传递还是按引用传递_第1张图片

针对复杂数据类型,以数组为例
例2

var arr1 = ['zyp','zyp','zyp']
var arr2 = arr1
arr2[0] = 'zyp1'
console.log(arr1)  //打印出 ["zyp1", "zyp", "zyp"]

以上例子的过程为:先在堆中开辟一块地址h1001来存数组[‘zyp’,‘zyp’,‘zyp’],同时将该堆内存的地址h1001存放在栈内存s103中,然后再在栈内存中开辟一个地址s104同样存放h1001,这时arr1和arr2指向同一块堆内存,改变其中的值会同时反映在变量arr1和arr2上。
JS中的函数参数传递到底是按值传递还是按引用传递_第2张图片
例3

var arr1 = ['zyp','zyp','zyp']
var arr2 = arr1
arr2 =  ['zyp1','zyp1','zyp1']
arr2[0] = 'zyp2'
console.log(arr2) //打印出 ["zyp2", "zyp1", "zyp1"]
console.log(arr1) //打印出 ["zyp", "zyp", "zyp"]

以上例子的过程为:跟上面一样,先在堆中开辟一块地址h1001来存数组[‘zyp’,‘zyp’,‘zyp’],同时将该堆内存的地址h1001存放在栈内存s103中,然后再在栈内存中开辟一个地址s104同样存放h1001,这时arr1和arr2指向同一块堆内存。不同的是:这时我们又在堆内存中开辟出一块新的地址h1002来存放新数组[‘zyp1’,‘zyp1’,‘zyp1’],新地址h1002存放在s104中,这时arr2中保存的地址已经由h1001变成了h1002, 这时再改变h1002对应的堆内存中的值,便和arr1没有任何关系了。
JS中的函数参数传递到底是按值传递还是按引用传递_第3张图片

明白了上述赋值过程再来理解函数传参便是一个道理了

function changeObj(arr1) {
	arr1= ['a1', 'a1', 'a1']
}
var arr = ['a', 'a', 'a']
changeObj(arr)
console.log(arr)  // 打印出["a", "a", "a"]

这个例子中:假设数组[‘a’, ‘a’, ‘a’]在堆内存中对应的地址为:h2001, 实参arr在栈内存中对应的地址为s201, 里面保存的是h2001。调用changeObj函数时,将arr复制给arr1,这里对应的操作是自动将在栈内存中分配一块地址s202来保存h2001,因此arr和arr1对应的是同一块堆内存,但这时又在堆内存中开辟新空间h2002来保存数组[‘a1’, ‘a1’, ‘a1’],h2002保存在arr1对应的栈内存s202中,这里的道理就和例3是一样的了

你可能感兴趣的:(JavaScript)