js嵌套函数作用域

y = 4
function a(y) {
  console.log(y)
}
function b() {
  let y = 3;
  a(y)
}
b() //结果为什么是3?不是4,函数a的作用域不是全局嘛?


//例子二
 y = 4
function a(y) {
  console.log(y)
}y
function b() {
  let y = 3;
  a()
}
b()  //undefined 不是4哦


//例子三
 y = 4
function a() {
  console.log(y)
}y
function b() {
  let y = 3;
  a()
}
b() //4

以上是否说明实参的作用域跟函数的作用域无关?

阅读 3k
3 个回答

老实说,总拿这种违反人类的写法去了解作用域只会加重作用域的迷惑,上述的代码真要放在一个合格的团队里至少它不会是成功,光代码格式化都已经会认为这是错误的了。

如果你在 TypeScript 下,它可能会是这样子:

const y = 4; // 不得不写上声明定义
function a(y: number) { // 不得不写上 `y` 类型
  console.log(y)
}
// other

可能你还有点懵,但如果你配合 TsLint 你会发现上面的代码压根就不让你通过,因为会让你得到一个 no-shadowed-variable 的警告,而你不得不改成这样子:

const y = 4;
function a(val: number) {
  console.log(val)
}
// other

最后你会发现这里压根没有所谓作用域的迷惑了,因为那些在你看来有迷惑的只不过没有良好的编码风格引起的,这里不存在 yy 之类的迷惑,val 就是一个简单不过的函数作用域,而 y 也只不过是全局作用域罢了,他们名称不同你在光看就很容易理解。

至于那些所谓的函数提升作用域,如果你严格按先声明后使用的规则,压根就没有这种事情存在。

再退一步讲,如果可能你还需要函数柯里化,可能会遇到嵌套作用域(或闭包),除非在做基础架构否则很难遇到,即便遇到届时你早就会用 class,那会你再想遇到闭包都难。

编程应该如何利用工具链,它会帮我们杜绝很多因为自身的不标准,倒置一些让人迷惑的事发生,但本身并不是语言的错,而更多的是历史问题

以上。

function函数的作用域取决于你执行的作用域 而不是声明时候的作用域

只有es6的箭头函数才是取决于你声明的作用域 而不是执行的作用域

-----上面回答草率了-----

首先函数作用域是有一个作用域链的
先看看题主的这块代码

y = 4
function a(y) {
  console.log(y)
}
function b() {
  let x = 3;
  a(x)
}
b()

在执行console.log(y)的时候此时作用域链[[Scopes]]有3块Local, Script, Global 题主聪明一眼就懂

首先就要去Local里面拿这个y,顺序是 Local --> Script ---> Global,那么Local里面有没有呢?有的 有一个行参y, 一旦有了这个形参效果就相当于 let y(内部自然不是这么实现的的); 所以 Local里面是有这个y的,y的值哪里来的,取决于调用的地方。

y = 4
function a(y) {
  console.log(y)
}
function b() {
  let x = 3;
  a()
}
b()

如果这个地方不传,那么打印出来的y就是undefined和外界没有任何关系

还有就是题主反驳我的问题

y = 4
function a() {
  console.log(y)
}
function b() {
  let y = 3;
  a()
}
b()

还是那个逻辑 执行a的时候a的作用域链有3层 Local --> Script ---> Global
在执行的过程中Local作用域中没有地方使用或者申明过y那么往上面一层找,Script其实就是js的执行环境 然后才是global 在浏览器里面也就是题主心心念念的window
所以这个地方确实是4 而不是3。

为什么[[Scopes]].Script里面没有? 在这里的提升只会提升到Global所以其实可以忽略这个

什么,你看到的[[Scopes]]只有Global? 那就当我没说

个人理解, 希望有大佬纠正。

这个其实就是看你理不理解作用域了,在你执行的时候,执行到a(x),会在b的作用域内找有没有变量x,如果没有,就沿着作用域链查找。因为,b的作用域内有一个x,所以实参的值就是3

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题