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

javascript中变量和对象之间的范围差异,javascript,angularjs,Javascript,Angularjs,有人能解释一下这两个javascript代码片段之间的区别吗: var orange={prop:“我是简单的水果”}; 控制台.log(橙色.prop)//输出:“我是简单的水果” 功能go(橙色){ orange.prop=“现在我已被函数更改”; }; 围棋(橙色); console.log(orange.prop);//输出:“现在我已被函数更改” . 在上面的块中,go函数明显改变了外部范围中的橙色变量/对象 . var apple=“我是简单的苹果”; console.log(

有人能解释一下这两个javascript代码片段之间的区别吗:

var orange={prop:“我是简单的水果”};
控制台.log(橙色.prop)//输出:“我是简单的水果”
功能go(橙色){
orange.prop=“现在我已被函数更改”;
};
围棋(橙色);
console.log(orange.prop);//输出:“现在我已被函数更改”
.
在上面的块中,
go
函数明显改变了外部范围中的
橙色
变量/对象
.

var apple=“我是简单的苹果”;
console.log(苹果);//输出“我是简单的苹果”
函数goApple(苹果){
apple=“现在我被函数改变了”;
};
苹果;
console.log(苹果);//输出“我是简单的苹果”
在此块中,外部
apple
变量保持不变
我在这里遗漏了一些基本的和明显的东西,或者javascript对于不同的变量类型是否有不同的范围规则

这条线

function goApple(apple) {
定义粗略定义局部变量的函数参数。这是您正在更改的局部变量,而不是外部变量


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

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

typeof apple //"string"
typeof orange //"object"
当传递字符串文本时,您传递的是不可变的数据,它是按值传递的,因此它不能更改


编辑:也就是说,
window.apple
指向的数据不能更改。更改
window.apple
的唯一方法是将其指向一些新数据<代码>window.apple=“新事物”

如果函数参数与外部变量的名称不同,您的问题可能会更清楚一些。实际上,您使用的是
apple
orange
作为全局变量和参数变量,它们在函数内部时会遮挡外部全局变量

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"
这里,
orange
orangeArg
指的是相同的值,它们从不更改所指的值。(在
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

引用的对象,这并不完全是范围界定;这是关于变量传递行为的。downvoter能解释我的答案中的错误吗?我不是downvoter,但可能是因为该语句-有点重复了我在问题中所说的,lol。也就是说,为什么外部作用域中橙色对象的属性发生了变化?thanks@MichaelColeman那我不知道什么对你来说不明显。您正在更改属性,它没有在本地范围中声明。是的,我想您所说的是因为:
函数go(orange){orange.prop="现在我……
orange.prop属性没有在函数内部声明,因此它将被分配给外部作用域上的
orange
对象?我只是想知道为什么不能在函数内部动态定义
prop
?虽然这里的信息是正确的,但我认为它对no也非常重要对于OP(@MichaelColeman):不变性意味着基于字符串的
apple
示例无法再现基于对象的
orange
示例的行为,但是
orange
示例可以展示
apple
示例的行为,例如通过
orange={prop:“全新对象”}
。Primitive immutability意味着您只能将字符串变量重新分配给一个新值(而不是修改值),但您始终可以重新分配变量的值,无论它是原语还是对象。谢谢,我认为@AlexanderBrevig给出的答案是对变量传递行为的一个良好、快速的洞察(借用你的话)我认为你的回答有助于在将来处理类似的代码时加深理解-刚刚投票通过,谢谢