JavaScript修改作用域外变量的方法与参数传递机制解析

作者:半夏

时间:2026-10-30

浏览:349

本文深入解析JavaScript中函数如何修改作用域外的变量,重点阐述“按共享传递”机制。通过对比基本类型与对象类型的行为差异,说明为何直接赋值无效而修改属性有效。同时梳理全局与局部作用域规则,帮助开发者准确掌握变量可见性与生命周期。

文章目录

JavaScript参数传递机制与按共享传递

在研读JavaScript相关教程并完成课后练习的过程中,我对函数参数传递机制进行了更深入的探究。

具体的练习题要求如下:

需要编写一个函数,使其能够修改作用域之外的变量。该函数接收一个由数字1到5组成的数组作为参数,调用后需将数组中的数字替换为对应的字符串表示。

解答此题需掌握以下核心知识点:

在JavaScript中,函数参数的传递行为取决于参数类型。对于数字、字符串和布尔值等基本类型,采用值传递方式,函数内部的修改不会反映到外部实参。而对于对象类型,传递的是引用,理论上对对象的修改会反映在主调程序中。然而,实际行为比简单的“按引用传递”更为复杂,具体表现如下文所示。


var outer_number = ;
var outer_boolean = true;
var outer_array = [,,];
var outer_object = {test:""};
function display(num,bool,arr,obj){
console.log("number:"+num+"\nboolean:"+bool+"\narray:"+arr+"\nobject:"+obj.test);
}
function test(num,bool,arr,obj){
display(num,bool,arr,obj);//num=,bool=true,array=[,,],object.test=
num = ;
bool = false;
arr[] = ;
obj.test = "";
display(num,bool,arr,obj);//num=,bool=false,array=[,,,],object.test=
arr = [,,];
obj = {test:""};
display(num,bool,arr,obj);//num=,bool=false,array=[,,],object.test=
}
test(outer_number,outer_boolean,outer_array,outer_object);
display(outer_number,outer_boolean,outer_array,outer_object);//num = ,bool=true,array=[,,,],object.test= 

上述代码示例中定义了4个全局变量,类型分别为数字、布尔值、数组和对象,以及两个函数:display和test。

调用display函数4次,每次的输出结果如下:

初始传入函数时的值显示为:number:2, boolean:true, array:1,2,3, object:122。

在函数内部执行更改后,值变为:number:0, boolean:false, array:1,2,3,3, object:134。

重新赋值后的状态为:number:0, boolean:false, array:3,2,1, object:133。

函数执行完毕后,全局变量的状态恢复为:number:2, boolean:true, array:1,2,3,3, object:134。

从结果可以看出,对数组和对象的重新赋值并未成功修改全局变量。如果JavaScript严格遵循按引用传递,全局变量应当被修改。实际上,JavaScript采用的是“按共享传递”(call by sharing)机制,而非严格的按引用传递。

在按共享传递模式下,函数接收到的是实参引用的副本。这与按引用传递的最大区别在于:对引用副本本身的赋值(如重新指向新对象)不会影响实参,但利用该副本修改对象内部属性或数组元素是有效的。

从可变性角度分析,对象是可变的,而基本类型是不可变的(注意:字符串的修改操作实际上返回的是新字符串)。因此,按共享传递机制对于基本类型而言,其行为表现与按值传递完全一致。

综上所述:

JavaScript中,基本类型和对象均按共享传递。但由于基本类型的不可变性,其按共享传递的表现等同于按值传递;而对象类型则通过共享传递允许修改其内部状态。

按共享传递(call by sharing)的定义是:传递实参引用的副本。对引用副本进行赋值操作不会影响实参的值,但可以通过副本修改所指向对象的内容。更多细节可参考相关技术文档。

函数对传入参数的处理规则总结如下:

1. 基本类型:按值传递(或视为按共享传递的特例)。在函数内部对参数进行赋值修改,不会影响主调程序中的原始变量。

2. 对象类型:按共享传递。传入的是实参引用的副本,对副本变量本身重新赋值无效,但对对象属性的修改或数组元素的变更是有效的。

以上是对JavaScript参数传递机制的理解,如有疏漏欢迎指正。

JavaScript变量作用域详解

接下来单独探讨JavaScript中的作用域概念。

所有程序设计语言都具备作用域概念,它决定了变量和函数的可访问范围,控制着可见性和生命周期。JavaScript主要包含全局作用域和局部作用域两种。

全局作用域(Global Scope)

在代码任何位置均可访问的对象拥有全局作用域。通常以下几种情况拥有全局作用域:

(1)最外层函数及其内部定义的变量拥有全局作用域,例如:


var authorName="山边小溪";
function doSomething(){
var blogName="梦想天空";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(authorName); //山边小溪
alert(blogName); //脚本错误
doSomething(); //梦想天空
innerSay() //脚本错误

(2)未定义直接赋值的变量会自动声明为拥有全局作用域,例如:


function doSomething(){
var authorName="山边小溪";
blogName="梦想天空";
alert(authorName);
}
doSomething(); //山边小溪
alert(blogName); //梦想天空
alert(authorName); //脚本错误 

变量blogName拥有全局作用域,而authorName仅在函数内部有效,在外部无法访问。

(3)所有window对象的属性拥有全局作用域。

一般情况下,window对象的内置属性(如window.name、window.location、window.top等)均拥有全局作用域。

1. 局部作用域(Local Scope)

与全局作用域相反,局部作用域仅在固定的代码片段内可访问,最常见于函数内部。因此有时也被称为函数作用域。例如代码中的blogName和函数innerSay仅拥有局部作用域。


function doSomething(){
var blogName="梦想天空";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(blogName); //脚本错误
innerSay(); //脚本错误 

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章