es6-函数默认值相关作用域问题

代码摘自es6入门

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}

foo() // 3
x // 1

里面有这么一句话

函数foo内部又声明了一个内部变量x,该变量与第一个参数x由于不是同一个作用域

然后我修改了一下

var x = 1;
function foo(x, y = function() { x = 2; }) {
  let x = 3;                   //修改了这
  y();
  console.log(x);
}

我的问题是既然不是同一作用域,为什么不能在内部用let声明x,
我知道不能let重复声明变量,但是解答说不是同一作用域

我的疑问及猜想:
难道预编译过程中不考虑当函数有默认参数时产生独立作用域,所以先判断了重复定义?
感觉很奇怪,个人感觉:编译器应该会将形参x应该会由let来声明它,这样才能突出产生了独立作用域

阅读 2.8k
4 个回答
var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}

foo() // 3
x // 1
函数foo内部又声明了一个内部变量x,该变量与第一个参数x由于不是同一个作用域

重新整理,之前说的还是错的,更正一下
foo的[[scope]]:
形参申明形式我认为是var x; let y = function () {x = 2}

go:x = 1;
作用域1{
    y=function() {x = 2};   //这边的x来自于y定义的携带的作用域中的x;就像闭包返回y并携带x
    作用域2{
       
        var x = 3;       x被重新声明提升了之前的x被覆盖但又存在与y闭包中    
    }
}
所以还是不能用let申明x
function foo(x, y = function() { x = 2; }) {
  let x = 3;                   //修改了这
  y();
  console.log(x);
}

这里let声明的x与形参重复,并不是与var x = 1;重复

参数变量是默认声明的,所以不能用let或const再次声明。

function foo(x = 5) {
  let x = 1; // error
  const x = 2; // error
}

摘自《ECMAScript 6 入门》阮一峰


这里,你引用的原文是:

函数foo内部又声明了一个内部变量x,该变量与第一个参数x由于不是同一个作用域

需要注意的是:

  • foo 内部又声明了一个内部变量 x,此处的 xvar 声明;
  • 与第一个参数 x,此处的 xlet/const 声明。

所以得出结论:不是同一个作用域

来,我们回到你的问题:既然不是同一作用域,为什么不能在内部用 let 声明 x

答案刚才已经得出:因为 varlet 不同,x 才不是一个作用域,现在你试图用 let 重复声明 第一个参数,自然会报错。


最早理解错了,不好意思,没仔细看你的问题

参数x=2 let x = 3 怎么不是同一作用域?
es6参数默认值声明我记得不知道从哪看的是相当于let 局部声明的(忘了)
走到默认值 也会走到let 重复声明的报错的 会抛出error
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏