JavaScript中默认函数参数的范围

我正在玩一些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实现细节。


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


慕标5832272
浏览 355回答 2
2回答

慕慕森

我不明白为什么这些例子不好因为默认初始化程序不在父作用域内评估,而是在函数作用域内评估。参数本身已经在范围内,因此您可以执行以下操作(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;  }})();

智慧大石

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

相关分类

JavaScript