gpt4 book ai didi

javascript - 为什么 block 赋值会改变全局变量?

转载 作者:行者123 更新时间:2023-12-01 14:50:16 27 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Function declaration in block moving temporary value outside of block?

(1 个回答)


2年前关闭。




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

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


在我看来,因为函数声明提升, a = 1a = 21会改变局部函数变量,所以 block 内会输出21,外面是0,但真正的结果是输出1外。

用chrome调试,结果是这样的

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

最佳答案

观察到的行为是非严格模式特有的,Firefox 也做同样的事情。

它这样做的原因是它遵循 Web 兼容性语义,如 Annex B 3.3 中所述。在规范中。

细节非常复杂,但这是引擎这部分的作者实现的:

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. 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)

...这就是发生的事情:

第 1 行: (var) a添加了外部作用域的变量环境, 0分配给它

第 2 行:创建了一个 if block , (let) a (即 function a() {} )被提升到 block 的顶部,阴影 (var) a
第 3 行: 1分配给 (let) a (注意,不是 (var) a )

第 4 行:(let) a 的值复制到 (var) a , 所以 (var) a变成 1

5号线: 2分配给 (let) a (注意,不是 (var) a )

第 7 行: (var) a打印到控制台(所以 1 打印)

Web 兼容性语义是尝试编码回退语义的行为集合,以使现代浏览器能够尽可能多地保持与 Web 上遗留代码的向后兼容性。这意味着它对在规范之外实现的行为进行编码,并且由不同的 vendor 独立实现。在非严格模式下,由于浏览器 vendor “走自己的路”的历史,几乎可以预料到奇怪的行为。

但是请注意,规范中定义的行为可能是沟通不畅的结果。 Allen Wirfs-Brock said在推特上:

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



... and :

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 给出了完全不同的结果( 0 由第一个 console.log 打印, 21 由最后一个 console.log 打印)。据我了解,这是因为 Safari 还没有对 Web 兼容性语义( example )进行编码。

故事的道德启示?使用严格模式。

More , details , herehere .

关于javascript - 为什么 block 赋值会改变全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61191014/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com