简体   繁体   English

JavaScript中默认函数参数的范围

[英]Scope of Default function parameters in javascript

I'm playing with some EcmaScript 2015 features and I must say that specification is rather hard to understand. 我正在玩一些EcmaScript 2015功能,我必须说该规范很难理解。

I totally understand that this code should throw error of some kind: 我完全理解这段代码应该引发某种错误:

(function(a = b, b = 1) { })();

And I know that default value could use outer scope: 而且我知道默认值可以使用外部范围:

(function() {
  let c = 1;
  return (function(a = c) { return a === 1; })();
})();

But I don't understand why these examples are not good: 但是我不明白为什么这些例子不好:

(function() {
  let a = 1;
  (function(a = a) { })();
})();

(function() {
  let b = 1;
  (function(a = b, b = 2) { })();
})();

My Chrome 59.0.3071.115 throws ReferenceError that variable is not defined. 我的Chrome 59.0.3071.115抛出ReferenceError,该变量未定义。

It seems that Chrome is doing some optimization where only 1 scope is created where all parameters set as inaccessible, and they are added one by one after their assignment. Chrome似乎在进行一些优化,其中仅创建1个作用域,将所有参数设置为不可访问,并在分配后将它们一一添加。

Some proof of this could be: 一些证明可能是:

(function(a = () => b, b = 2) { return a() === 2; })();

This looks like an missing opportunity for my taste and I'm wondering does specification force to use only 1 scope here or this is only v8 implementation details. 我觉得这似乎是一个错失的机会,我想知道规范是否在这里只使用1个作用域,或者这仅仅是v8实现细节。

Could somebody please point me to place in specification which could clarify this? 有人可以指出我在规范中可以澄清这一点吗?

I don't understand why these examples are not good 我不明白为什么这些例子不好

Because the default initialisers are not evaluated in the parent scope, but rather inside the function scope. 因为默认初始化程序不在父作用域内评估,而是在函数作用域内评估。 The parameters themselves are already in scope, so that you can do something like 参数本身已经在范围内,因此您可以执行以下操作

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

Could somebody please point me to place in specification which could clarify this? 有人可以指出我在规范中可以澄清这一点吗?

The relevant section is §9.2.12 FunctionDeclarationInstantiation . 相关章节是第9.2.12FunctionDeclarationInstantiation

I must say that specification is rather hard to understand. 我必须说,规范很难理解。

Yes it is, although it's written for engine implementors not for programmers. 是的,尽管它是为引擎实现者而非程序员编写的。 However, the explanatory note basically confirms your understanding of the optimisation 但是,解释性说明基本上可以确认您对优化的理解

If the function's formal parameters do not include any default value initializers then the body declarations are instantiated in the same Environment Record as the parameters. 如果函数的形式参数不包含任何默认值初始化程序,则主体声明将在与参数相同的环境记录中实例化。 If default value parameter initializers exist, a second Environment Record is created for the body declarations. 如果存在默认值参数初始化程序,则会为主体声明创建第二个环境记录。

Your examples basically desugar to 您的示例基本上是对

(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;
  }
})();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM