JavaScript原始值与引用值的操作本质解析
本文深入解析JavaScript中原始值与引用值的操作机制。通过对比赋值、函数传参及比较三个维度,阐明原始值传递副本而引用值传递地址的本质差异。文章结合代码示例,详细说明了重新赋值对原数据的影响,以及函数内部修改参数时引用覆盖与属性修改的不同结果,帮助开发者准确理解数据内存行为。
原始值与引用值操作核心结论
核心结论:原始值在变量赋值或函数传参时,均不会改变原值;引用值在变量赋值或函数传参时,若新变量重新赋值则不影响原引用,但若直接操作原对象或数组,则会改变原引用值。
首先需明确,值与类型是两个独立概念。例如,null是null类型的唯一值,undefined是undefined类型的唯一值,true和false是boolean类型仅有的两个值。在任何编程语言中,值的操作均可归纳为以下三个方面。
复制值:即将值赋值给新变量,或通过变量将值赋给另一个变量、属性或数组元素。
传递值:即将值作为参数传递给函数或方法。
比较值:即将值与另一个值进行比较,判断是否相等。
由于值类型数据和引用型数据的存储形式不同,操作它们的方法及结果也有所区别。需注意,当值为值类型数据时,常称为原始值或基本值;当值为引用型数据时,常称为引用值或复合值。
原始值的操作机制
1.使用原始值
对于原始值,其操作的三个层面说明如下。
1)复制值
在赋值语句中,操作过程会产生实际值的副本,副本与实际值之间无关联,它们分别位于不同的栈区或堆区。该副本可存储于变量、对象属性或数组元素中。例如:
var n = 123, a, b = [], c = {};
a = n; // 复制数字123
b[0] = n; // 复制数字123
c.x = n; // 复制数字123
(a == b[0]) && (a == c.x) && (b[0] == c.x) && alert("复制的值都是相等的"); // 检测它们的值都是相等的
在上述示例中,分别将值123复制3份给变量a、数组b和对象c。虽然它们的值相等,但彼此相互独立。
2)传递值
当把值传递给函数或方法时,传递的仅是副本,而非值本身。例如,若在函数中修改传递进来的值,结果仅影响该参数值的副本,不会影响原来的值。
var a = 123; // 原来的值
function f(x){
x = x + x;
}
f(a); // 调用函数修改传递的值
alert(a); // 查看变量a的值是否受影响,返回值为123,说明没有变化
3)比较值
在上述示例中也可看到,当对原始值进行比较时,进行逐字节比较以判断是否相等。比较的是值本身,而非值所处的位置,因此比较结果可能相等,但这仅说明它们包含的字节信息相同。
引用值的操作机制
2.使用引用值
对于引用值,其操作的三个层面说明如下。
1)复制值
在赋值语句中,所赋的值是对原值的引用,而非原值副本或原值本身。也就是说,赋值后变量保存的都是对原值的引用(即原值的存储地址)。当在多个变量、数组元素或对象属性间复制时,它们均与原始变量保存的引用相同。
所有引用具有相同的效力和功能,均可执行操作。若通过其中一个引用编辑数据,这种修改将在原值及其他相关引用中体现出来。例如:
var a = [1,2,3]; // 赋值数组引用
b = a; // 复制值
b[0] = 4; // 修改变量b中第一个元素的值
alert(a[0]); // 返回4,显示变量a中第一个元素的值也被修改为4
但是,若给变量b重新赋予新值,则新值不会影响原值内容。例如:
var a = [1,2,3]; // 赋值数组引用
b = a; // 复制值
b = 4; // 为变量b重写赋值
alert(a[0]); // 变量a的内容保持不变
重复赋值实际上是覆盖变量对原值的引用,变为另一个值的副本或对其引用。因此不会对原值产生影响,演示示意图如图4-2所示。

2)传递值
当使用引用将数据传递给函数时,传递给函数的也是对原值的一个引用。函数可以使用这个引用来修改原值本身,任何修改在函数外部都是可见的。例如:
var a = [1,2,3];
function f(x){
x[0] = 4; // 在函数中修改参数值
}
f(a); // 传递引用值
alert(a[0]); // 返回4,原值发生变化
请注意,在函数内修改的是对外部对象或数组的引用,而不是对象或数组本身的值。在函数内可以使用引用来修改对象的属性或数组的元素,但是如果在函数内部使用一个新的引用覆盖原来的引用,那么在函数内部的修改就不会影响原引用的值,函数外部也是看不到的。
var a = [1,2,3];
function f(x){
x = 4; // 在函数中修改参数值
}
f(a); // 传递引用值
alert(a[0]); // 返回1,原值不会发生变化
3)比较值
当比较两个引用值时,比较的是两个引用地址,看它们引用的原值是否为同一个副本,而不是比较它们的原值字节是否相等。当对两个不同值进行引用时,尽管它们具有相同的字节构成,但这两个引用的值却是不相等的。
var a = new Number(1); // 引用值a
var b = new Number(1); // 引用值b
var c = a; // 把a的引用赋值给c
alert(a==b); // 返回false
alert(a==c); // 返回true
所以,{} == {},[] == [],都返回false。因为引用地址不同。
值类型与引用型的运算差异
总之,对于任何语言来说,使用值和使用引用都是数据操作的两种基本方法。当我们操作数据时,采用什么方法进行处理,主要看数据的类型。值类型和引用型数据参与运算的方式不同,值类型数据通过使用值来操作数据,而引用型数据使用引用来操作数据。运算方式的不同,自然所产生的结果也不同。我们不妨再看一个示例:
var s = "abc"; // 字符串,值类型数据
var o = new String(s); // 字符串对象,被装箱后的字符串
function f(v){ // 运算函数
v.toString = function(){ // 修改参数的方法toString()
return 123;
};
}
f(s); // 传入值
alert(s); // 返回字符串"abc",说明运算没有对原数据造成影响
f(o); // 传入引用
alert(o); // 返回数值123,说明运算已经影响到原数据的内部结构
值类型是以实际值参与运算的,因此与原数据没有直接联系。而引用型以引用地址参与运算,计算的结果会影响到引用地址所关联的堆区数据块。但是,有一点例外,对于JavaScript的字符串来说,它的操作方法就比较复杂,详情请google!
以上这篇JavaScript数据操作_浅谈原始值和引用值的操作本质就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
