Javascript值传递与引用传递
什么是值传递、参数传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数;
引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
值传递的数据类型
string
number
boolean
undefined
null
Javascript 中值传递的数据类型有string
、number
、boolean
、undefined
、null
,可以看出都是简单的数据类型。这些类型的值作为参数传递时,传递给函数的只是它的一个副本,修改形参不会更改实参(函数外部)的值。
var str = 'val';
var num = 1;
var bol = true;
var undf = undefined;
var nu = null;
function changeVal(a, b, c, d, e){
a = 'value';
b = 2;
c = false;
d = 'javascript';
e = 'es6';
}
changeVal(str, num, bol, undf, nu);
// 输出结果
console.log(str); // val
console.log(num); // 1
console.log(bol); // true
console.log(undf); // undefined
console.log(nu); // null
引用传递的数据类型
object
array
function
在Javascript: The Good Parts
里面是这样描述对象引用的:
对象通过引用来传递。它们永远不会被复制
var stooge = {};
var x = stooge;
x.nickname = 'Curly';
var nick = stooge.nickname; // x 和stooge 指向同一个对象的引用, nick 为 'Curly'
var a = {}, b = {} ,c = {};
// a, b, c 每个都引用一个不同的空对象
var a = b = c = {};
// a, b, c 都引用同一个空对象 a.name = 'xiaoming' ==> b.name === 'xiaoming'
除了object
类型,其他复杂类型如array
、function
其实也是引用传递。
var user = {};
var list = [];
var animal = function(){
};
function change(obj, arr, fn){
obj.age = 20;
arr.push('xiaoming');
fn.prototype.say = function(){
alert('hello world');
};
};
change(user, list, animal);
var cat = new animal();
console.log(user); // age: 20
console.log(list); // ["xiaoming"]
cat.say(); // hello world
对象user
、数组list
、方法animal
传递给change函数的是它们的引用(内存地址),修改函数里形参obj
、arr
、fn
,实参(函数外部)同样被更改。因为它们指向的都是同一个内存地址。
Javascript中引用传递的特殊情况:
var user = {};
var list = [];
var animal = function(){
this.name = 'hello world';
};
function change(obj, arr, fn){
obj = {age: 20}
arr = ['xiaoming']
fn = function(){
this.name = 'hello javascript';
}
};
change(user, list, animal);
var cat = new animal();
console.log(user); // {}
console.log(list); // []
console.log(cat); // animal {name: "hello world"}
这里就很奇怪了,明明同样是引用传递,为什么值会没有改变呢?
借用上述的The Good Parts
例子说明:
var a = {};
var b = a;
b.age = 20;
console.log(a.age);
函数的引用传递就好比b = a
,当b属性更改,引用a的属性肯定被更改。
var a = {};
var b = {age: 20};
console.log(a.age);
修改引用参数本身的值,其实就等于重新赋值,这个时候b跟a就没有关系了,修改b的属性不会更改到a。
小结
- 值传递的数据类型
string
、number
、boolean
、undefined
、null
- 引用传递类型
object
、array
、function
- 如果修改引用参数本身的值,并不会改变引用本身;如果修改引用的内部成员值,就会修改引用的值