关于词法作用域和闭包的一点疑问

2020-05-04 11:45:36 +08:00
 Aloehuang

let a = 0;

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

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

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

addone();

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

3792 次点击
所在节点    JavaScript
38 条回复
YadongZhang
2020-05-04 11:48:55 +08:00
log 的是全局的 a,let 和 var 是不是有区别
Aloehuang
2020-05-04 11:49:40 +08:00
YadongZhang
2020-05-04 11:51:22 +08:00
@Aloehuang #2 javascript.info 了解一下,有图解
Aloehuang
2020-05-04 11:53:36 +08:00
@YadongZhang var 和 let 在这里没有区别,结果都是 0.
你给的网站内容太多了,找不到具体要查找的问题
rabbbit
2020-05-04 11:54:07 +08:00
js 的作用域是词法作用域,不是动态作用域.
secondwtq
2020-05-04 11:54:25 +08:00
楼主所期望的行为恰恰是 Lexical Scoping 的反面,即 Dynamic Scoping
把这两个的定义都找来,对比一下就能明白了
YadongZhang
2020-05-04 11:56:39 +08:00
@Aloehuang #4 有搜索框,关键词 Closure,addThree() 调用的是全局 a,函数里的变量只能在函数块里使用,log 找不到的
ljpCN
2020-05-04 11:57:05 +08:00
这个例子应该没有涉及闭包吧,闭包主要是把一些局部作用域的变量保持着不被回收掉。
然后,这个你只看词法作用域就行了,只有 this 那种东西才要看运行时的调用吧。
Aloehuang
2020-05-04 11:57:13 +08:00
@rabbbit 有没有这方面的文章可以看看?您这样说不是特别理解
rabbbit
2020-05-04 11:57:23 +08:00
词法作用域: 在哪定义,在哪往上找变量
静态作用域: 在哪调用,在哪往上找变量
rabbbit
2020-05-04 11:58:21 +08:00
静态作用域 -> 动态作用域
rabbbit
2020-05-04 12:00:11 +08:00
上边那个"静态作用域"写错了

词法(静态)作用域: 在哪定义,在哪往上找变量
动态作用域: 在哪调用,在哪往上找变量
Dyon
2020-05-04 12:13:53 +08:00
全局有一个 a,前两个函数又在自己的作用于中定义了一个新的 a,当他们调用名为 a 的变量的时候会现在自己的作用域中找,找到了就调用它,这时候全局的那个 a 就被忽略了。第三个函数的作用域中没有名为 a 的变量,于是它调用了全局的 a 。这里用 let 还是 var 结果是一样的因为这里都是函数,如果是在 for 等块级语法中,let 和 var 才会不一样。
Aloehuang
2020-05-04 12:14:23 +08:00
@secondwtq 谢谢,一针见血
Aloehuang
2020-05-04 12:15:54 +08:00
@Dyon 那第三个函数为什么不从第二个函数里面找 a
mrcode
2020-05-04 12:18:52 +08:00
JavaScript 是词法作用域,不是动态作用域
YadongZhang
2020-05-04 12:21:48 +08:00
@Aloehuang #15 全局 a 注释掉,其他两个函数体都加一个 console.log(a) 就有答案了
Dyon
2020-05-04 12:36:31 +08:00
@Aloehuang 哦刚刚误解楼主的问题了,楼主应该是想问动态作用域与静态作用域,不过即使不了解这些,根据运行结果也能推断出来 js 的作用域链是根据定义的位置确定而非调用的位置,是静态的
huangbangsheng
2020-05-04 13:47:21 +08:00
高性能 JavaScript 开篇解释了你的问题
zhengjian
2020-05-04 13:58:30 +08:00
@YadongZhang 全局 a 注释掉就报错了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/668409

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX