js作用域的问题

如何解释下面的两端代码运行结果

1

a中回调b,b打印x。b为什么拿不到a中的x;

let a=fn=>{const x=1;fn();};
let b=()=>{console.log(x)};

a(b);  //Uncaught ReferenceError: x is not defined

2

let a=fn=>{ x=1;fn();};
let b=()=>{console.log(x)};

x;   // Uncaught ReferenceError: x is not defined

a(b); // 1
阅读 2.5k
5 个回答

这个问题主要是箭头函数的作用域问题。

箭头函数的作用域在定义时就绑定好了。

第一题:

  • 执行a(b)
  • a函数中定义x变量,并执行b
  • 但b函数的作用域,在定义时就已经绑定为window,window中没有x,故报错,x is not defined。

第二题:

  • 打印x,这是两个函数都没执行,故报错,x is not defined。
  • 执行a(b)
  • a函数中直接给x赋值,由于没有声明,会直接赋值到window对象上,这时window.x = 1。
  • 执行b,b的作用域在window,所以自然就能打印出x

作用域是看文法环境的。在1中,首先b的函数作用域中没有变量x的定义,然后就去作用域链的上层去找。这一步很关键,作用域链的上层是‘b函数定义’所在的环境,我们假设b函数是在全局定义的,那b函数作用域的上层就是全局作用域。很明显在全局作用域下没有x变量。 不同是是在2中,定义x时没有用关键字,所以x还就是一个全局变量(也就是在demo和面试题中这么写,项目中会被骂死的)

变量的作用域链是看你在代码中声明变量时候定好的,和执行时候的读取变量的位置无关。
当程序执行,读取到这个变量时候,就按照声明时候定好的作用域链进行寻找。

因为你声明函数的地方都是在外部,所以只能取到最外层的变量,而你第二个x没有加var或let,默认是一个全局的变量。

新手上路,请多包涵

箭头函数的作用域问题

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