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
内存分布如下:
改变前:
栈内存 | 堆内存 | ||
value | 1 | ||
v | 1 |
改变后:
栈内存 | 堆内存 | ||
value | 1 | ||
v | 2 |
例子二:
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} |
o | 2 |
关键点:
运算符=
就是创建或修改变量在内存中的指向.
初始化变量时为创建,重新赋值即为修改.
首先一个非常简单的例子:
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} |
然后一步一步执行代码:
- 创建变量a指向
对象{b: 1}
; - 创建变量c指向
对象{b: 1}
; - a重新指向常量区的
2
;
栈 | 堆 | 常量区 |
---|---|---|
a | 2 | |
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]] | |
b | 1 |
执行完a.b = 2
后:
栈 | 堆 | 常量区 |
---|---|---|
a,c | [[Object]] | |
b | 2 |
那么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
不管是基本数据类型还是对象类型的,都是拷贝。前者拷贝值,后者拷贝地址值。
深圳半价门票、半价美食,关注【深圳摩天轮】公众号,各种福利资源,交友活动,摩天轮特价票