为什么块分配值会更改全局变量? [英] Why does block assigned value change global variable?

查看:55
本文介绍了为什么块分配值会更改全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

var a = 0;
if (true) {
  console.log(a)
  a = 1;

  function a() {}
  a = 21
  console.log(a)
}
console.log(a)

在我看来,由于函数声明的提升,a = 1a = 21会更改局部函数变量,所以in块中将输出21,而outside为0,但实际结果是在output 1之外.

In my opinion, because function declaration hoisting, a = 1 and a = 21 will change local function variable ,so in block will output 21,and outside is 0,but the true result is outside output 1.

使用chrome调试,结果是这样

Debug with chrome, result like that

function a() {}上运行时,它将更改局部变量和全局变量.太奇怪了? 谁能给我一些解释?

When running on function a() {} ,it will change local and global variable. so weird? Who can give me some explanation?

推荐答案

观察到的行为是非严格模式所特有的,并且Firefox执行相同的操作.

The observed behavior is peculiar to non-strict mode, and Firefox does the same thing.

之所以采用这种方式,是因为它遵循了

The reason it is behaving this way, is that it is following the Web Compatibility Semantics, as described in Annex B 3.3 in the spec.

细节非常复杂,但这是该部分引擎实现的内容:

The details are very complicated, but here is what the authors of this part of the engine implemented:

当内部功能a存在于块中,处于草率模式时以及何时 Web兼容性语义适用(在 规范),然后:

When an inner function a exists in a block, in sloppy mode, and when the Web Compatibility Semantics apply (scenarios described in the spec), then:

  1. 内部功能a通过类似于let的块作用域("(let) a")悬挂在块中()
  2. 同时,在包含以下内容的范围中创建了一个变量,其名称也为a但具有var语义(即函数作用域) 块("(var) a")
  3. 到达声明内部函数的行时,(let) a的当前值将被复制到(var) a(!!)
  4. 从块内部对名称a的后续引用将引用(let) a
  1. Inner function a is hoisted with let-like block scope inside the block ("(let) a")
  2. At the same time, a variable, also with name a, but with var semantics (ie. function scope), is created in the scope containing the block ("(var) a")
  3. When the line declaring the inner function is reached, the current value of (let) a is copied into (var) a (!!)
  4. Subsequent references to name a from inside the block will refer to (let) a

因此,对于以下情况:

1:  var a = 0
2:  if(true) {
3:    a = 1
4:    function a() {}
5:    a = 2
6:  }
7:  console.log(a)

...这是发生了什么

...this is what happens:

第1行: (var) a被添加到外部作用域的可变环境中,并为其分配了0

Line 1: (var) a is added the the variable environment of the outer scope, and 0 is assigned to it

第2行:创建了一个if块,将(let) a(即function a() {})提升到该块的顶部,使(var) a

Line 2: An if block is created, (let) a (ie. the function a() {}) is hoisted to the top of the block, shadowing (var) a

第3行: 1被分配给(let) a(注意,不是(var) a)

Line 3: 1 is assigned to (let) a (note, not (var) a)

第4行:(let) a的值被复制到(var) a,因此(var) a变为1

Line 4: The value of (let) a is copied into (var) a, so (var) a becomes 1

第5行: 2被分配给(let) a(注意,不是(var) a)

Line 5: 2 is assigned to (let) a (note, not (var) a)

第7行: (var) a已打印到控制台(因此已打印1)

Line 7: (var) a is printed to the console (so 1 is printed)

Web兼容性语义是一组行为的尝试,这些行为试图对后备语义进行编码,以使现代浏览器能够尽可能多地与Web上的旧代码保持向后兼容性.这意味着它将对规范外部实施的行为进行编码,并由不同的供应商独立进行.在非严格模式下,由于浏览器供应商走自己的路"的历史,几乎可以预期会有奇怪的行为.

The web compatibility semantics is a collection of behaviors that try to encode a fallback semantic to enable modern browsers to maintain as much backwards compatibility with legacy code on the Web as possible. This means it encodes behaviors that were implemented outside of the spec, and independently by different vendors. In non-strict mode, strange behaviors are almost expected because of the history of browser vendors "going their own way."

但是,请注意,规范中定义的行为可能是错误沟通的结果. Allen Wirfs-Brock 在Twitter上说:

Note, however, that the behavior defined in the specification might be the result of a miscommunication. Allen Wirfs-Brock said on Twitter:

无论如何,根据我想像的任何合理解释,最后报告的a == 1的...结果都是不正确的.

In any case, the reported... result of a==1 at the end isn’t correct by any reasonable interpretation that I ever imagined.

... :

应该是function a(){}!因为在该块内,对a的所有显式引用都是对块级绑定的.只有隐式的B.3.3分配应转到外部a

It should be function a(){}! Because within the block, all explicit references to a are to the block-level binding. Only the implicit B.3.3 assignment should go to the outer a

最后的注释:Safari,给出了完全不同的结果(第一个console.log打印0,最后一个console.log打印21).据我了解,这是因为Safari尚未对Web兼容性语义进行编码(示例).

Final note: Safari, gives a totally different result (0 is printed by the first console.log, and 21 is printed by the final console.log). As I understand it, this is because Safari simply does not yet encode the Web Compatibility Semantics (example).

故事的道德?使用严格模式.

Moral of the story? Use strict mode.

更多此处.

这篇关于为什么块分配值会更改全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆