JavaScript深入之参数按值传递

定义

在《JavaScript高级程序设计》第三版 4.1.3,讲到传递参数:

ECMAScript中所有函数的参数都是按值传递的。

什么是按值传递呢?

也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

按值传递

举个简单的例子:

var value = 1;
function foo(v) {
    v = 2;
    console.log(v); //2
}
foo(value);
console.log(value) // 1

很好理解,当传递 value 到函数 foo 中,相当于拷贝了一份 value,假设拷贝的这份叫 _value,函数中修改的都是 _value 的值,而不会影响原来的 value 值。

引用传递?

举个例子:

var obj = {
    value: 1
};
function foo(o) {
    o.value = 2;
    console.log(o.value); //2
}
foo(obj);
console.log(obj.value) // 2

第三种传递方式

不急,让我们再看个例子:

var obj = {
    value: 1
};
function foo(o) {
    o = 2;
    console.log(o); //2
}
foo(obj);
console.log(obj.value) // 1

例子一:

var value = 1;
function foo(v) {
    v = 2;
    console.log(v); //2
}
foo(value);
console.log(value) // 1

内存分布如下:

改变前:

栈内存堆内存
value1
v1
改变后:
栈内存堆内存
value1
v2

例子二:

var obj = {
value: 1
};
function foo(o) {
    o.value = 2;
    console.log(o.value); //2
}
foo(obj);
console.log(obj.value) // 2

内存分布如下:

改变前:

栈内存堆内存
obj,o指针地址{value: 1}
改变后:
栈内存堆内存
obj,o指针地址{value: 2}

例子三:

var obj = {
value: 1
};
function foo(o) {
    o = 2;
    console.log(o); //2
}
foo(obj);
console.log(obj.value) // 1

内存分布如下:

改变前:

栈内存堆内存
obj,o指针地址{value: 1}
改变后:
栈内存堆内存
obj指针地址{value: 1}
o2

关键点:

运算符=就是创建或修改变量在内存中的指向.

初始化变量时为创建,重新赋值即为修改.

首先一个非常简单的例子:

var a = {b: 1};// a = {b: 1}
var c = a;// c = {b: 1}
a = 2;// 重新赋值a
console.log(c);// {b: 1}

接着是上一段代码在内存中的分布:

a, c{b: 1}

然后一步一步执行代码:

  1. 创建变量a指向对象{b: 1};
  2. 创建变量c指向对象{b: 1};
  3. a重新指向常量区的2;
常量区
a2
c{b: 1}

所以c从始至终都是指向对象{b: 1}.

var value = 1;
function foo(v) {
    v = 2;
    console.log(v); //2
}
foo(value);
console.log(value) // 1

将案例一等价替换:

var value = 1;
function foo() {
    var v = value; // 创建变量v指向value所指向的值
    v = 2;// v重新指向另外的值
    console.log(v); //2
}
foo(value);
console.log(value) // 1,value从始至终都未改变指向.

案例三也可以这样替换.

接着分析案例二:

修改一下我的第一个例子:

var a = {b: 1};// a = {b: 1}
var c = a;// c = {b: 1}
a.b = 2;// 重新赋值对象a中的属性b
console.log(c);// {b: 2},// c也随着修改,从

在内存中的分布:

常量区
a,c[[Object]]
b1

执行完a.b = 2后:

常量区
a,c[[Object]]
b2

那么a,c从始至终都未改变指向,只是b改变了而已

第一张内存分布图将{b: 1}放入堆中,是为了大家更方便抓住重点

所以案例二等量替换为

var obj = {
   value: 1
};
function foo() {
   var o = obj;
   o.value = 2;// 变量value改变了指向,而o并未改变
   console.log(o.value); //2
}
foo(obj);
console.log(obj.value) // 2




不管是基本数据类型还是对象类型的,都是拷贝。前者拷贝值,后者拷贝地址值。