深入理解JavaScript参数传递机制:值传递与共享传递

作者:拾光

时间:2026-10-22

浏览:561

本文深入解析JavaScript函数参数传递机制,澄清按值传递与按引用传递的区别。通过代码示例说明基本类型按值传递,而引用类型采用共享传递(传递引用的副本),解释了为何修改对象属性会影响原对象,但重新赋值参数却不会。

文章目录

JavaScript参数传递机制概述

在ECMAScript规范中,所有函数参数均采用按值传递的方式处理。

那么,什么是按值传递?

简单来说,按值传递意味着将函数外部的变量值复制一份,赋值给函数内部的参数变量。这个过程与将一个变量的值复制到另一个变量完全一致。

按值传递与引用传递辨析

按值传递机制

以下是一个基础示例:


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

该机制易于理解:当变量value被传入函数foo时,系统会创建该值的一个副本(假设命名为_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

这里存在一个常见的困惑点:《JavaScript高级程序设计》(俗称“红宝书”)明确指出ECMAScript所有参数均为按值传递,上述示例为何看似实现了引用传递的效果?

这是否意味着JavaScript支持真正的引用传递?

按共享传递:JavaScript的真实机制

实际上,还存在第三种传递方式。

请观察另一个对比示例:


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

如果JavaScript采用引用传递,外部变量obj的值应当被修改,但实际输出显示obj.value仍为1。这表明JavaScript并非采用引用传递。那么,真实的机制是什么?

这引出了第三种传递方式:按共享传递(Call by Sharing)。

按共享传递的定义是:在传递对象时,传递的是对象引用的副本(copy of the reference),而非对象本身的副本,也非直接传递引用。

关键区别在于:按引用传递直接传递对象的引用,而按共享传递传递的是该引用的副本。

因此,在函数内部通过参数修改对象的属性(如o.value),可以通过副本引用找到并修改原对象;但如果直接对参数变量重新赋值(如o = 2),仅修改了副本引用的指向,不会影响外部原始对象。前文提到的后两个示例均属于按共享传递。

总结而言,可以这样理解:

若参数为基本类型(如Number、String等),则按值传递;若参数为引用类型(如Object、Array等),则按共享传递。

由于传递引用的副本本质上也是一种“值”的拷贝,因此《JavaScript高级程序设计》等权威资料中通常统一将其描述为按值传递,以简化概念。

这就是为何红宝书等经典教材将其统称为按值传递的原因。

系列文章介绍

系列介绍

JavaScript深入系列完整目录请访问:https://github.com/mqyqingfeng/Blog 。

JavaScript深入系列计划撰写约十五篇文章,旨在梳理JavaScript底层核心知识,重点解析原型链、作用域链、执行上下文、变量对象、this指向、闭包、参数传递机制、call/apply/bind方法、new操作符及继承等难点概念。

以上就是本文的全部内容,希望能为读者的学习提供有益帮助,欢迎继续支持本站内容。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章