范围 JavaScript 中变量和对象之间的差异

Scoping Differences between variables and objects in javascript

本文关键字:之间 对象 JavaScript 变量 范围      更新时间:2023-09-26

有人可以解释一下这两个javascript片段之间的区别吗:

var orange = { prop: "i am simple fruit"};
console.log(orange.prop);  //output: "i am simple fruit"
function go(orange) {
    orange.prop = "Now i have been changed by the function";
};
go(orange);
console.log(orange.prop); // output: "Now i have been changed by the function"

.
在上面的块中,go函数显然改变了外部范围内的
orange变量/对象.

var apple = "i am simple apple";
console.log(apple); // output "i am simple apple"
function goApple(apple) {
    apple = "Now i have been changed by the function";
};
goApple(apple);
console.log(apple); // output "i am simple apple"

在此块中,外部apple变量保持不变
我在这里缺少一些基本和明显的东西,或者 javascript 对变量类型有不同的范围规则?

区别在于您传递的参数的类型。

typeof apple //"string"
typeof orange //"object"

传递字符串文本时,您传递的是不可变数据,并且它是按传递的,因此它无法更改。

编辑:也就是说,window.apple指向的数据无法更改。更改window.apple的唯一方法是将其指向一些新数据。 window.apple = "something new";

此行

function goApple(apple) {
定义一个

函数参数,该参数大致定义一个局部变量。这是您要更改的局部变量,而不是外部变量。

当你对orange执行相同的操作时,你也有一个局部变量,但你没有改变局部变量的值,只是这个值的一个属性(因此它恰好是与外部作用域相同的橙色对象(。

Javascript 将始终按值传递函数参数。在第一种情况下,您正在访问通过引用传递的对象的属性。当 apple 传递给函数时,该引用将复制到橙色。因此,两者都引用内存中的同一对象

如果您的函数参数与外部变量的名称不同,您的问题可能会更清晰一些。实际上,您将appleorange用作全局变量和参数变量,它们在函数内部隐藏外部全局变量。

var apple = "i am simple apple";
console.log(apple); // output "i am simple apple"
function goApple(appleArg) {
    appleArg = "Now i have been changed by the function";
};
goApple(apple);
console.log(apple); // output "i am simple apple"

在这里,您将更改appleArg引用的值。这对外部变量apple引用的值没有影响。

orange示例中,您正在修改对象本身,而不是引用该对象的任何变量。

var orange = { prop: "i am simple fruit"};
console.log(orange.prop);  //output: "i am simple fruit"
function go(orangeArg) {
    orangeArg.prop = "Now i have been changed by the function";
};
go(orange);
console.log(orange.prop); // output: "Now i have been changed by the function"

在这里,orangeorangeArg 引用相同的值,并且它们永远不会更改它们引用的值。(在apple示例中,appleArg变量更改为引用与 apple 不同的值。但是,值本身会发生变化(因此两个变量都引用的单个值会更改,但两个变量都不会更改它所引用的值(。

对于字符串,您无法修改值本身,因为基元是不可变的。使用对象,可以修改值的属性。考虑第三种情况,我们更改变量引用的值:

var mango = { prop: "i am simple fruit"};
console.log(mango.prop);  //output: "i am simple fruit"
function go(mangoArg) {
    mangoArg = { prop: "Now i have been changed by the function" };
};
go(mango);
console.log(mango.prop); // output: "i am simple fruit"

在这里,我们以与修改appleArg相同的方式更改了mangoArg。我们mangoArg引用一个全新的值,而不是修改 mango 引用的对象。