简体   繁体   English

从函数中重新分配全局变量

[英]Reassigning a global variable from within a function

In one part of a (Udacity) lesson on JavaScript objects, it says that because primitives are immutable, any changes made to an argument inside a function effectively creates a copy local to that function, without affecting the primitive outside of it. 在关于JavaScript对象的(Udacity)课程的一部分中,它说因为基元是不可变的,所以对函数内部的参数所做的任何更改都会有效地创建该函数的局部副本,而不会影响它之外的基元。 This is the example provided: 这是提供的示例:

function changeToEight(n) {
  n = 8; // whatever n was, it is now 8... but only in this function!
}

let n = 7;

changeToEight(n);

console.log(n); // 7

However, as shown in the following example, you can change the value assigned to a global variable from within a function (as long as the variable name isn't passed as an argument): 但是,如以下示例所示,您可以在函数内更改分配给全局变量的值(只要变量名称不作为参数传递):

let counter = 1;

function changeCounter() {
  counter = 2;
}

changeCounter();
console.log(counter); // 2

If primitives are immutable, why is the variable mutable in the latter example? 如果原语是不可变的,为什么变量在后一个例子中是可变的? Does the example provided in the lesson actually have anything to do with primitives not being immutable, or is it just because the variable name in the function is identical to the name of the argument passed to the function? 本课程中提供的示例实际上与原语不是不可变的有关,还是因为函数中的变量名称与传递给函数的参数名称相同?

Values are immutable, not variables. 值是不可变的,而不是变量。 Variables can be constant but that is a different topic. 变量可以是常量,但这是一个不同的主题。

Value immutability means that you can't do 1 = 2 or 'hello' = 'world' for it doesn't make sense (in case you have primitive values). 价值不变性意味着你不能做1 = 2'hello' = 'world'因为它没有意义(如果你有原始值)。

On the other hand, object's are mutable, therefore you can change their internal structure. 另一方面,对象是可变的,因此您可以更改其内部结构。

obj = {
  name: 'John'
};
obj.name = 'Sue';

But you can make object immutable as well by using Object.freeze(obj) (just be careful because that produces only a shallow immutability). 但是你可以通过使用Object.freeze(obj)使对象不可变(只是要小心因为它只产生一个浅的不变性)。


What you mean is a constant variable - variable that can't be reassigned. 你的意思是一个constant变量 - 无法重新分配的变量。 So you can't do something like 所以你不能做类似的事情

const x = 1;
x = 2;

But again, you can change the internal state of a value that is stored in a constant variable if it is an object (change in properties of an object doesn't count as reassignment). 但同样,如果它是一个对象,则可以更改存储在常量变量中的值的内部状态(对象属性的更改不计入重新分配)。


In your first example, it actually doesn't matter if it is a primitive value or object. 在您的第一个示例中,它实际上与原始值或对象无关。 The same thing would occur even if it was an object. 即使它是一个对象,也会发生同样的事情。 It is the reassignment that produces a local copy. 重新分配是产生本地副本的。

 function changeToEight(n) { n = [8]; } let n = [7]; changeToEight(n); console.log(n); 

Only in-place changes to that object wouldn't produce a new local variable with the same name (for example: Array.prototype.push method, if we consider an array). 只有对该对象的就地更改才会产生具有相同名称的新局部变量(例如: Array.prototype.push方法,如果我们考虑一个数组)。

 function changeToEight(n) { n.push(8); } let n = [7]; changeToEight(n); console.log(n); 


Your second example is different because function changeChouter doesn't have its own local variable called n . 你的第二个例子是不同的,因为函数changeChouter没有自己的局部变量n According to scope resolution rules, variables, when referenced, are first searched for in a local scope, if that fails, they are searched for in an enclosing scope next. 根据范围解析规则,引用时的变量首先在本地范围中搜索,如果失败,则在下一个封闭范围中搜索它们。

That variable n , because it is not local to your function, is searched for in changeChouter 's enclosing scope, which is the global scope in this case, where it is found. 该变量n ,因为它不是你的函数的本地变量,在changeChouter的封闭范围中搜索,在这种情况下,它是找到它的全局范围。 Which means that you are reassigning that global variable. 这意味着您要重新分配该全局变量。

So your code is basically equivalent to 所以你的代码基本上相当于

 let counter = 1; counter = 2; console.log(counter); 

function changeToEight(n)

assigns a local variable as n due to the argument, and you are assigning that local variable within the changeToEight function with 8. It's not effecting the global n variable. 由于参数,将局部变量赋值为n ,并且您将changeToEight函数中的局部变量赋值为8.它不会影响全局n变量。 If you had done like 如果你做得像

 function changeToEight(m) { n = 8; // global variable n is now 8...! but local variable m is 7..! } let n = 7; changeToEight(n); console.log(n); // 8 cool..! 

all would be as expected... 一切都会如预期的那样......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM