JavaScript变量、传值与传址机制详解

作者:闭包旅人

时间:2026-10-30

浏览:547

本文深入解析JavaScript中变量、传值与传址的核心机制。详细区分基本类型(如number、string)与引用类型(如Array、Object)在内存中的存储差异。通过四个典型代码案例,阐明函数参数传递时“复制变量值”的行为:基本类型复制数值,引用类型复制指针。重点解释为何直接赋值参数会切断外部引用,而修改对象属性仍会影响原对象,帮助开发者准确理解JS内存模型与变量作用域。

文章目录

JavaScript变量类型与参数传递机制概述

首先梳理核心结论:

1. JavaScript中的变量包含两种类型的值:引用类型和基本类型。引用类型涵盖Array、Object和Function(可理解为非基本类型均属此类);五种基本类型分别为undefined、null、string、boolean和number。

2. 函数参数的传递机制本质上是复制变量值。

教材指出:“将函数外部的值复制给函数内部参数,等同于将一个变量赋值给另一个变量。基本类型的传递与基本类型变量的复制一致,而引用类型的传递则与引用类型变量的复制一致。”

“当变量复制引用类型的值时,系统会将存储在变量对象中的值复制一份到新变量的空间中。不同之处在于,这个副本实际上是一个指针,指向堆内存中的一个对象。复制操作完成后,两个变量引用同一个对象。因此,修改其中一个变量会影响另一个变量。”

【注意:只有复制引用类型的值时,才涉及传址概念】

3. 参数本质上是函数的局部变量。

----------------------------------------------------------------------------

传值与传址的基本概念与内存分布

基本概念解释:

传值:将A的数值传递给B,修改B时A不受影响,因为B存储的是与A相同的值; 传址:将A的地址传递给B,修改B时A随之改变,因为B存储的是A的地址(类似于电脑中的快捷方式)。

值类型(value type)数据存储在栈内存的变量中。即在栈中分配内存空间,直接存储所包含的值,该值即代表数据本身。值类型数据具有较快的存取速度。

引用类型(reference type)数据不驻留在栈中,而是存储于堆内存。即在堆中分配内存空间,不直接存储所包含的值,而是指向所存储的值,该值代表指向的地址。访问引用类型数据时,需先在栈中检查变量内容,该变量引用堆中的实际数据。引用类型数据比值类型数据占用更大的存储规模,且访问速度较低。

----------------------------------------------------------------------------

函数参数传递的四个典型案例分析

以下是三个典型问题。

【问题1】:为什么执行change(a)函数后,外部的a没有受到影响?


<script>
var a = [1, 2, 3];
function change(a) {
 console.log(a);//[1,2,3]
 a = 2;   //传值
 console.log(a);//2
}
change(a);
console.log(a);  //[1,2,3] 
</script>

问题1解答:change(a)的执行过程如下:首先将对象a(数组)传入change函数,并复制给change的参数a。随后执行a=2赋值语句,此时变为传值操作。由于a=2是值类型,不涉及引用地址问题,因此并未影响外部的a。

【问题2】:为什么执行change(a)函数后,外部的a受到了影响?


<script>
 var a = [1, 2, 3];
 function change() { 
  a = 2;//传值
 }
 change();
 console.log(a);  //2 
</script>

问题2解答:执行change()时,函数在其执行环境中查找作用域链。活动对象(activation object)不包含变量a,于是沿作用域链向上查找,直到全局执行环境找到变量a。此时函数内部的a和外部的a在内存上指向同一地址,因此函数内部a发生变化时,外部a也会随之改变。

解析:问题2与问题1的区别在于,问题2并未引入参数,因此不涉及复制变量的操作。

【问题3】:为什么执行change(a)函数后,外部的a受到了影响?


<script>
 var a = [1, 2, 3];
 function change(b) { 
  b[0] = 2;
 }
 change(a);
 console.log(a);  //[2,2,3]
</script>

问题3解答:此问题与问题1非常相似,唯一区别在于a=2换成了b[0]=2。起初令人困惑的是:既然说是复制,参数b应该是复制值,为何会影响外部的a?

确实,change函数执行时,参数b是a的复制值。因为a是引用类型,所以在函数内部b和a按引用访问的是同一个地址的对象。b[0]=2的出现,并不影响函数内部b和a引用的是同一个对象这一事实。

【问题4】:为什么执行change(a)函数后,外部的a没有受到影响?


 var a = [1, 2, 3];
 function change(b) { 
  console.log(b);//[1,2,3]
  b=2;
  b[0] = 2;
 }
 change(a);
 console.log(a);  //[1,2,3]

问题4解答:change(b)的执行过程如下:a对象传入change函数,将值和地址复制给b。执行b=2后,b变为值类型,不再涉及地址引用问题。此后b[0]=2实际上毫无意义,因为此时b已不是数组,自然不具备b[0]这样的索引方式。因此,b与a的地址引用关系在b=2执行后即已消失。此时外界的a仍然是[1,2,3]。

以上即为本文的全部内容,希望对大家有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章