技术解析

关于词法作用域和闭包的一点疑问
0
2021-08-17 23:07:42
idczone

let a = 0;

function addone() { let a = 10; addtwo(); }

function addtwo() { let a = 20; addthree(); }

function addthree() { console.log(a); }

addone();

结果为 0,为什么不是 20 呢?不是说一层一层从调用上下文查找直到全局上下文吗?


log 的是全局的 a,let 和 var 是不是有区别

我是从这里找到的词法作用域和闭包
https://blog.hhking.cn/2018/09/08/i-never-understood-javascript-closures/

javascript.info 了解一下,有图解

var 和 let 在这里没有区别,结果都是 0.
你给的网站内容太多了,找不到具体要查找的问题

js 的作用域是词法作用域,不是动态作用域.

楼主所期望的行为恰恰是 Lexical Scoping 的反面,即 Dynamic Scoping
把这两个的定义都找来,对比一下就能明白了

有搜索框,关键词 Closure,addThree() 调用的是全局 a,函数里的变量只能在函数块里使用,log 找不到的

这个例子应该没有涉及闭包吧,闭包主要是把一些局部作用域的变量保持着不被回收掉。
然后,这个你只看词法作用域就行了,只有 this 那种东西才要看运行时的调用吧。

有没有这方面的文章可以看看?您这样说不是特别理解

词法作用域: 在哪定义,在哪往上找变量
静态作用域: 在哪调用,在哪往上找变量

静态作用域 -> 动态作用域

上边那个"静态作用域"写错了
词法(静态)作用域: 在哪定义,在哪往上找变量
动态作用域: 在哪调用,在哪往上找变量

全局有一个 a,前两个函数又在自己的作用于中定义了一个新的 a,当他们调用名为 a 的变量的时候会现在自己的作用域中找,找到了就调用它,这时候全局的那个 a 就被忽略了。第三个函数的作用域中没有名为 a 的变量,于是它调用了全局的 a 。这里用 let 还是 var 结果是一样的因为这里都是函数,如果是在 for 等块级语法中,let 和 var 才会不一样。

谢谢,一针见血

那第三个函数为什么不从第二个函数里面找 a

JavaScript 是词法作用域,不是动态作用域

全局 a 注释掉,其他两个函数体都加一个 console.log(a) 就有答案了

哦刚刚误解楼主的问题了,楼主应该是想问动态作用域与静态作用域,不过即使不了解这些,根据运行结果也能推断出来 js 的作用域链是根据定义的位置确定而非调用的位置,是静态的

高性能 JavaScript 开篇解释了你的问题

全局 a 注释掉就报错了

所以说 addThree() 函数里的 a 和其他两个函数体的 a 没有关系

建议重新看闭包
数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服