JavaScript 赋值机制与参数传递详解
在 JavaScript 开发中,变量赋值和函数传参的行为往往容易混淆。核心在于区分原始值(Primitive Values)和引用值(Reference Values)。原始值直接存储在栈内存中,复制时生成独立副本;而引用值指向堆内存中的对象,赋值时传递的是内存地址的引用。理解这一机制是掌握 JS 底层逻辑的关键。
原始值与引用值的基础概念
要理解赋值机制,首先需明确两种基本数据类型的区别:
- 原始值(Primitive Values):包括
Undefined、Null、Boolean、Number和String。它们在内存中以固定的大小存在于栈(Stack)中,按值访问。 - 引用值(Reference Values):通常指
Object及其子类型(包括数组、函数等)。它们的大小不固定,实际对象数据存储在堆(Heap)中,变量在栈中仅保存指向堆内存的地址。
注意以下代码中的细微差别:
var a = 'test'; // 原始值字符串
var b = new String('test'); // 引用值对象
var A = 'true'; // 原始值布尔/字符串(取决于上下文,此处为字符串字面量即原始值逻辑下的对比)
var B = new Boolean('true'); // 引用值对象
变量 a 和 A 存储的是具体的值,而 b 和 B 存储的是指向堆内存中对象的指针。
赋值机制:拷贝与引用
当我们将一个变量赋值给另一个变量时,JavaScript 会根据数据类型采取不同的策略。
第1步:原始值的赋值(按值拷贝)
对于原始值,赋值操作会在栈内存中创建一个新的独立区域,将原变量的值复制一份放入新区域。此后两个变量互不干扰。
var a = 1; // 栈中存放值 1
var b = a; // 复制一份值 1 给 b,b 也指向新的栈空间
b = 2; // 修改 b 的值
alert(a); // 输出 1,a 不受影响
第2步:引用值的赋值(按址引用)
对于引用值,赋值操作仅在栈内存中复制那份“地址指针”,而非堆中的实际对象。因此,多个变量可能指向堆中的同一个对象。
var A = new Object(); // 在堆中创建对象,栈中存地址
A.x = 1;
var B = A; // B 获得与 A 相同的地址指针,两者指向同一堆对象
B.x = 2; // 通过 B 修改对象属性
alert(A.x); // 输出 2,因为 A 和 B 监控的是同一个对象
函数参数传递机制
函数调用时的参数传递同样遵循上述规则。无论参数是原始值还是引用值,JavaScript 始终是按值传递的,只是这个“值”对于原始值是数据本身,对于引用值则是内存地址。
第1步:传递原始值参数
当原始值作为参数传入函数时,形参接收的是实参值的副本。在函数内部修改形参,不会影响外部的实参变量。
var a = 1;
function test(m) {
m = 2; // 修改的是局部副本 m,不影响外部变量 a
}
test(a);
alert(a); // 输出 1
第2步:传递引用值参数
当引用值作为参数传入函数时,形参接收到的是实参指向对象的地址。虽然形参变量本身在栈中的地址副本不能被修改以指向其他对象(一旦重新赋值则断开联系),但可以通过该地址修改堆内存中对象的属性,从而影响外部变量。
var A = new Object();
A.x = 1;
function test(M) {
M.x = 2; // 通过地址修改堆内存中的属性
}
test(A);
alert(A.x); // 输出 2,外部对象被修改
综合案例分析
结合开篇的实际代码,我们可以清晰判断变量在函数执行后的状态:
var a = 'test'; // 原始值
var b = function() {}; // 引用值(函数也是对象)
b.a = 'test'; // 给函数对象添加属性
function change(m, n) {
m = 'change'; // 1. m 是原始值拷贝,修改 m 不影响 a
n.a = 'change'; // 2. n 是 b 的地址拷贝,修改 n.a 直接影响 b 的对象属性
}
change(a, b);
分析结果
- 变量
a:作为原始值(字符串)传入函数,形参m获得了值的拷贝。m = 'change'仅改变了局部变量m,函数结束后,外部变量a仍保持为'test'。 - 变量
b:作为引用值(函数对象)传入函数,形参n获得了b的内存地址。n.a = 'change'修改了该地址指向的对象属性。因此,外部变量b的属性a会被更新为'change'。
总结而言,JavaScript 的赋值与传参机制统一且严格:栈内存负责存储原始值和对象指针,堆内存负责存储实际对象。操作时需时刻警惕引用共享带来的副作用,特别是在处理复杂对象时。
以上就是 JavaScript 赋值机制与参数传递的详细内容,更多关于 JavaScript 基础教程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













