本文解析JavaScript中函数参数的传递机制。基础类型按值传递,修改副本不影响外部;对象和数组按引用传递,直接修改属性或元素会反映到原变量。但若在函数内对参数重新赋值,则仅影响局部变量,不会改变外部引用。
JavaScript参数传递机制概述
今天遇到一个常见问题:如何修改函数内部参数,使其影响函数外部的变量?例如以下代码:
<script>
var myname = "wood";
A(myname);
document.write(myname);
function A(n) {
n = "Yao";
}
</script>
输出结果仍为wood。这表明当字符串变量myname传入A函数后,函数内部实际上创建了一个名为myname的副本,其初始值与外部变量相同。在函数体内对该副本进行的任何操作,仅作用于该副本,不影响外部原始变量。
然而,当传入的参数类型为数组或对象时,情况有所不同。在函数内部对参数进行的修改(如更改元素或属性),会直接反映到外部的原始变量上。
数组与对象的引用传递特性
<script>
var myname = ["wood"];
A(myname);
document.write(myname[0]);
function A(n) {
n[0] = "Yao";
}
</script>
从上述代码可以看出,friut数组的第一个元素已被成功修改。
以下是针对对象的具体示例:
<script>
var myname = {name1:"wood"};
A(myname);
document.write(myname.name1);
function A(n) {
n.name1 = "Yao";
}
</script>
可以明显看到,函数内部对参数属性的修改直接影响了外部原始变量。这与基础类型参数的传递方式有本质区别,需要特别注意。
但是,如果在函数内部对传入的数组或对象执行重新赋值操作,这种更改不会反映到函数外部的原始变量上。
请观察以下代码:
函数内重新赋值的局限性
<script>
var myname = {name1:"wood"};
A(myname);
document.write(myname.name1);
function A(n) {
n = {name1:"Yao"};
}
</script>
根据前述理论,你可能认为执行A()函数后,myname变量的name1属性值已变为'Yao'。但实际结果可能令人意外。
原因在于,当在函数内部使用赋值语句(如 n = {...})时,系统创建了一个新的局部变量p(此处指代函数参数n指向的新对象)。对该新对象的赋值仅在函数内部有效,外部的myname变量仍然指向原来的对象,因此其值未变。
这一行为与之前代码的关键区别在于:是在函数内部直接修改参数的属性或数组元素,还是对参数本身进行重新赋值。
下面我们通过传递对象的方式,重新实现一个时钟数字格式化输出的示例:
实际应用:时钟格式化示例
<script>
var mytime = self.setInterval(function() {
getTime();
}, 1000);
//alert("ok");
function getTime() {
var timer = new Date();
var t = {
h: timer.getHours(),
m: timer.getMinutes(),
s: timer.getSeconds()
}
//将时间对象t,传入函数checkTime(),直接在checkTime()中改变对象中的值。
//而无需再去接收返回值再赋值
checkTime(t);
document.getElementById("timer").innerHTML = t.h + ":" + t.m + ":" + t.s;
}
function checkTime(i) {
if (i.h < 10) {
i.h = "0" + i.h;
}
if (i.m < 10) {
i.m = "0" + i.m;
}
if (i.s < 10) {
i.s = "0" + i.s;
}
}
</script>
该示例使用setInterval()函数定时调用刷新事件,也可以利用setTimeout()在getTime()中进行递归调用来实现相同功能。
以上就是本文的全部内容,希望对大家学习javascript程序设计有所帮助。