JavaScript中默认功能参数的范围 [英] Scope of Default function parameters in javascript

查看:87
本文介绍了JavaScript中默认功能参数的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩一些EcmaScript 2015功能,我必须说规范很难理解。



我完全明白这个代码应该会抛出一些错误()();();();(b)(b)

我知道默认值可以使用外部范围:

 (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正在进行一些优化,其中只创建了一个范围,其中所有参数设置为不可访问,并在它们分配后逐个添加。



有些证明可以是:

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

这看起来像是一个缺少机会的我的口味,我想知道规格力只使用1这里的范围或者这只是v8实现细节。



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

解决方案


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


因为默认的初始化程序不在父范围内进行评估,而是在函数范围内。参数本身已经在范围内,因此您可以执行类似

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




有人可以指出我可以澄清这个说明吗?


相关部分是§9.2.12FunctionDeclarationInstantiation


我必须说规范是相当难以理解。


是的,虽然它是为引擎实现者编写而不是程序员。但是,解释性说明基本上证实了您对最优化的理解。



如果函数的形式参数不包含任何默认值初始化函数,那么体例声明在相同的环境记录作为参数。如果默认值参数初始化器存在,则会为身体声明创建第二个环境记录。



您的示例基本上是非常糟糕的

 (function(){
let a = arguments [0]!== undefined?arguments [0]:b,
// ^清楚一个ReferenceError
b = arguments [1]!== undefined?arguments [1]:1;
{
}
})();

(function(){
let c = 1;
return(function(){
let a = arguments [0]!== undefined?arguments [ 0]:c;
// ^按照你的想法,
{
return a === 1;
}
})();
})();

(function(){
let a = 1;
(function(){
let a = arguments [0]!== undefined?arguments [0 ]:a;
// ^再次清楚一个ReferenceError
{
}
})();
})();

(function(){
let b = 1;
(function(){
let a = arguments [0]!== undefined?arguments [0 ]:b,
//还是一个ReferenceError
b = arguments [1]!== undefined?arguments [1]:2;
{
}
} )();
})();

(function(){
let a = arguments [0]!== undefined?arguments [0]:()=> b,
//
b = arguments [1]!== undefined?arguments [1]:2;
{
return a()=== 2;
}
}) ();


I'm playing with some EcmaScript 2015 features and I must say that specification is rather hard to understand.

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.

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.

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.

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.

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

这篇关于JavaScript中默认功能参数的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆