为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript中默认函数参数的范围

JavaScript中默认函数参数的范围

慕标5832272 2019-11-21 09:30:45
我正在玩一些EcmaScript 2015功能,我必须说该规范很难理解。我完全理解这段代码应该引发某种错误:(function(a = b, b = 1) { })();而且我知道默认值可以使用外部范围:(function() {  let c = 1;  return (function(a = c) { return a === 1; })();})();但是我不明白为什么这些例子不好:(function() {  let a = 1;  (function(a = a) { })();})();(function() {  let b = 1;  (function(a = b, b = 2) { })();})();我的Chrome 59.0.3071.115抛出ReferenceError,该变量未定义。Chrome似乎在进行一些优化,其中仅创建1个作用域,将所有参数设置为不可访问,并在分配后将它们一一添加。一些证明可能是:(function(a = () => b, b = 2) { return a() === 2; })();我觉得这似乎是一个错失的机会,我想知道规范是否在这里只使用1个作用域,或者这仅仅是v8实现细节。有人可以指出我在规范中可以澄清这一点吗?
查看完整描述

2 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

我不明白为什么这些例子不好


因为默认初始化程序不在父作用域内评估,而是在函数作用域内评估。参数本身已经在范围内,因此您可以执行以下操作


(function(a = 2, b = a) { console.log(b); }());

有人可以指出我在规范中可以澄清这一点吗?


相关章节是第9.2.12节FunctionDeclarationInstantiation。


我必须说,规范很难理解。


是的,尽管它是为引擎实现者而非程序员编写的。但是,解释性说明基本上可以确认您对优化的理解


如果函数的形式参数不包含任何默认值初始化程序,则主体声明将在与参数相同的环境记录中实例化。如果存在默认值参数初始化程序,则会为主体声明创建第二个环境记录。


您的示例基本上是对


(function() {

  let a = arguments[0] !== undefined ? arguments[0] : b,

//                                                    ^ clearly a ReferenceError

      b = arguments[1] !== undefined ? arguments[1] : 1;

  {

  }

})();


(function() {

  let c = 1;

  return (function() {

    let a = arguments[0] !== undefined ? arguments[0] : c;

//                                                      ^ works as you'd think

    {

      return a === 1;

    }

  })();

})();


(function() {

  let a = 1;

  (function() {

    let a = arguments[0] !== undefined ? arguments[0] : a;

//                                                      ^ again clearly a ReferenceError

    {

    }

  })();

})();


(function() {

  let b = 1;

  (function() {

    let a = arguments[0] !== undefined ? arguments[0] : b,

//                                                      ^ still a ReferenceError

        b = arguments[1] !== undefined ? arguments[1] : 2;

    {

    }

  })();

})();


(function() {

  let a = arguments[0] !== undefined ? arguments[0] : () => b,

//                                                          ^ works indeed

      b = arguments[1] !== undefined ? arguments[1] : 2;

  {

    return a() === 2;

  }

})();


查看完整回答
反对 回复 2019-11-21
?
智慧大石

TA贡献1946条经验 获得超3个赞

因此,看起来a =案例无论如何都不可行。如果每个默认值都将在自己的范围内进行评估,则a = b的情况可能可行。但这对于引擎来说将是过多的开销,因此开发板的所有参数只能使用1个作用域。看起来这里的规范很明确。谢谢。

查看完整回答
反对 回复 2019-11-21
  • 2 回答
  • 0 关注
  • 354 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信