按值传递和按引用传递

按值传递 VS. 按引用传递

按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。

按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。

按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。

按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低。两种传值方式都有各自的问题。

例子:

按值传递

1
2
3
4
5
6
7
8
function change(num){
// 这里对num这个变量创建了一个内存的副本
var num=num+1;
return num;
}
var num=1;
console.log("内部的",change(num)); //2
console.log("外部的",num); //1

按引用传递

1
2
3
4
5
6
7
8
9
10
11
12
var obj={
name:"xiaoming"
}
function change2(obj){
//当前obj对内存的这个地址指向同一个
obj.age=20;
console.log("内部的",obj)
}
change2(obj)
console.log("外部的",obj)
//内部的{name:"xiaoming,age:20}
//外部的{name:"xiaoming,age:20}

按引用传递:object,array(js对象)
按值传递:string,number,boolean

对于想复制对象但是不想保持引用关系,此时就需要深拷贝.
对于深拷贝,网上教程很复杂,但现在浏览器普遍都支持ES5以上了,直接使用JSON.parse(JSON.stringify(xxx)) 就行

1
2
3
4
5
6
7
8
9
10
// 浅拷贝
var arr1=[1,2,3,4,5]
var arr2=arr1;
arr1[3]=100
console.log(arr2);//[ 1, 2, 3, 100, 5 ]
// 深拷贝
var arr1=[1,2,3,4,5]
var arr2=JSON.parse(JSON.stringify(arr1))
arr1[3]=100
console.log(arr2);//[ 1, 2, 3, 4, 5 ]