参数如何影响函数中的变量值?



我目前正在学习JavaScript,我有一个关于函数参数的问题。我有这个功能:

//Function 1
let from = 'Ann';
function showMessage(from, text) {
from = 'Jane';
alert(from + ' says ' + text);
}
showMessage(from, 'Hello');
alert(from);
//Function 2
let userName = 'John';
function showMessage1(){
userName = 'Bob'
alert('Hello '+ userName);
}
alert(userName);
showMessage1();
alert(userName);

我可以理解在 Function1 中showMessage(from, 'Hello');显示Jane says Helloalert(from)显示Ann因为当我传递参数时,该函数会创建我传递的值的本地副本。我读过,当你有一个同名的全局变量和局部变量时,局部阴影全局,我认为它发生在函数 1 中,这就是为什么我在最后一行得到"Ann"的原因。

然后,由于我没有将任何参数传递给 Function2,因此它不会创建本地副本,这就是为什么userName的值等于Bob并且显示在最后一行。

编辑:我改写我的问题:如果我看到的唯一区别是一个传递参数而另一个不是,为什么它们的行为不同(一个不覆盖全局变量,另一个覆盖全局变量(?

这是因为您尚未在showMessage1中声明局部变量userName。变量是用关键字之一声明的varletconst(我不会在这里讨论差异,尽管它们很重要(。如果这样做,那么将得到预期的结果:

//Function 1
let from = 'Ann';
function showMessage(from, text) {
from = 'Jane';
alert(from + ' says ' + text);
}
showMessage(from, 'Hello');
alert(from);
//Function 2
let userName = 'John';
function showMessage1(){
let userName = 'Bob'
alert('Hello '+ userName);
}
alert(userName);
showMessage1();
alert(userName);

在您的代码段中,由于在赋值userName = 'Bob'之前没有let(或varconst(,因此没有称为userName的局部变量要分配给,因此它会分配给封闭作用域中的userName变量 - 这里是全局作用域。这就是为什么在您的示例中,全局userName被覆盖,但它不在上面的版本中。

编辑:我

改写我的问题:如果我看到的唯一区别是一个传递参数而另一个不是,为什么它们的行为不同(一个不覆盖全局变量,另一个覆盖全局变量(?

明确回答这个问题:区别与是否传递参数无关。区别在于函数内部赋值是局部变量还是非局部变量(在本例中为全局变量(。在你的showMessage中,赋值是给from,根据定义,它是一个局部变量,因为它是一个函数参数。在原始showMessage1中,userName赋值是封闭(全局(作用域中的非局部变量,因为在函数的作用域中没有声明userName。通过使用let(或varconst(声明变量,在函数内部创建一个该名称的局部变量,然后将其分配给该变量,而不会影响封闭作用域中的同名("阴影"(变量。

一个非常简略的规则集是JS不会在"byValue"和"byReference"之间做出决定。至少不像其他编程语言那样这样做。所有原始类型都由 Value 传递(字符串布尔值和数字等(。compund变量(例如OBJECTS和ARRAY(是通过引用传递的。仅此而已。没有关键词可以告诉他们采取不同的行动。如果要按值放置数组或对象,请创建它的副本。如果要通过引用获得基元类型 - 创建基元类型的对象。类型较少的语言,如Javascript或REXX,以及其他一些处理不同的东西,如在编译器上中继的语言。编译器必须确切地知道该做什么。在脚本语言中,我们有一个很好的口译员,他可以在最后一秒决定什么是对的,什么是错的。:) .oO(有时通过这样的行为会产生一些白发;)

最新更新